如何对字符串进行URL编码

xon*_*rlz 188 iphone objective-c nsstring ipad ios

我有一个NSString带有空格和&字符的URL字符串().如何url编码整个字符串(包括&&符号和空格)?

cho*_*own 287

不幸的是,stringByAddingPercentEscapesUsingEncoding并不总是100%工作.它对非URL字符进行编码,但仅保留保留字符(如斜杠/和&符号&).显然这是Apple意识到的错误,但由于他们尚未修复它,我一直在使用此类别对字符串进行url编码:

@implementation NSString (NSString_Extended)

- (NSString *)urlencode {
    NSMutableString *output = [NSMutableString string];
    const unsigned char *source = (const unsigned char *)[self UTF8String];
    int sourceLen = strlen((const char *)source);
    for (int i = 0; i < sourceLen; ++i) {
        const unsigned char thisChar = source[i];
        if (thisChar == ' '){
            [output appendString:@"+"];
        } else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' || 
                   (thisChar >= 'a' && thisChar <= 'z') ||
                   (thisChar >= 'A' && thisChar <= 'Z') ||
                   (thisChar >= '0' && thisChar <= '9')) {
            [output appendFormat:@"%c", thisChar];
        } else {
            [output appendFormat:@"%%%02X", thisChar];
        }
    }
    return output;
}
Run Code Online (Sandbox Code Playgroud)

像这样使用:

NSString *urlEncodedString = [@"SOME_URL_GOES_HERE" urlencode];

// Or, with an already existing string:
NSString *someUrlString = @"someURL";
NSString *encodedUrlStr = [someUrlString urlencode];
Run Code Online (Sandbox Code Playgroud)

这也有效:

NSString *encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
                            NULL,
                            (CFStringRef)unencodedString,
                            NULL,
                            (CFStringRef)@"!*'();:@&=+$,/?%#[]",
                            kCFStringEncodingUTF8 );
Run Code Online (Sandbox Code Playgroud)

关于这个主题的一些好的阅读:

Objective-c iPhone百分比编码一个字符串?
Objective-C和Swift URL编码

http://cybersam.com/programming/proper-url-percent-encoding-in-ios
https://devforums.apple.com/message/15674#15674 http://simonwoodside.com/weblog/2009/4/ 22/how_to_really_url_encode /

  • @chown [男孩,那个类别的方法看起来确实很熟悉!](http://stackoverflow.com/questions/3423545/objective-c-iphone-percent-encode-a-string/3426140#3426140) (105认同)
  • @DaveDeLong这可能是我得到它的地方.在我的所有项目中它已经是一年左右的标准类别,所以我想你可能是原始来源!我编辑了措辞,所以看起来我并没有因为写作而受到赞扬. (31认同)
  • 为什么你会使用这样一个复杂的类别,而不是直接下降到[CFURLCreateStringByAddingPercentEscapes()](http://developer.apple.com/library/ios/documentation/CoreFoundation/Reference/CFURLRef/Reference/reference.html #// apple_ref/doc/uid/20001206-CH1g-F16659),您可以在其中明确指定要始终转义的字符. (12认同)
  • @KevinBallard因为CF函数适用于包容模型("逃避这些字符"),通常你想要一个独家模型("逃避所有*除了*这些字符") (8认同)
  • 为什么?if(thisChar ==''){[output appendString:@"+"]; 如果它会像我期望的那样用%20编码空格 (4认同)
  • 为什么它将'{space}'替换为'+'而不是'%20'?我不得不改变它. (2认同)

Nis*_*ant 127

这可能会有所帮助

NSString *sampleUrl = @"http://www.google.com/search.jsp?params=Java Developer";
NSString* encodedUrl = [sampleUrl stringByAddingPercentEscapesUsingEncoding:
 NSUTF8StringEncoding];
Run Code Online (Sandbox Code Playgroud)

对于iOS 7+,推荐的方法是:

NSString* encodedUrl = [sampleUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
Run Code Online (Sandbox Code Playgroud)

您可以根据URL组件的要求选择允许的字符集.

  • 这也没有正确编码参数分隔符,如'&','?' 在您将内容传递到API的情况下. (7认同)
  • 这不起作用.这不会转换成%26. (5认同)
  • stringByAddingPercentEscapesUsingEncoding 已弃用“使用 `-stringByAddingPercentEncodingWithAllowedCharacters:` 代替,它始终使用推荐的 UTF-8 编码,并为特定的 URL 组件或子组件编码,因为每个 URL 组件或子组件对哪些字符有效有不同的规则。” (2认同)

Pet*_*ese 89

自选择答案后添加了新的API; 您现在可以使用NSURLUtilities.由于URL的不同部分允许使用不同的字符,因此请使用适用的字符集.以下示例编码以包含在查询字符串中:

encodedString = [myString stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
Run Code Online (Sandbox Code Playgroud)

要专门转换"&",您需要将其从网址查询集中删除或使用其他集合,因为在网址查询中允许使用"&":

NSMutableCharacterSet *chars = NSCharacterSet.URLQueryAllowedCharacterSet.mutableCopy;
[chars removeCharactersInRange:NSMakeRange('&', 1)]; // %26
encodedString = [myString stringByAddingPercentEncodingWithAllowedCharacters:chars];
Run Code Online (Sandbox Code Playgroud)

  • `NSMakeRange('&',1)`在Swift中不起作用,因为Swift不允许char转换为int而没有hacks.要在Swift代码中使用此解决方案,请使用`removeCharactersInString("&")`而不是`.removeCharactersInRange(...)` (3认同)

Oli*_*son 16

Swift 2.0示例(兼容iOS 9)

extension String {

  func stringByURLEncoding() -> String? {

    let characters = NSCharacterSet.URLQueryAllowedCharacterSet().mutableCopy() as! NSMutableCharacterSet

    characters.removeCharactersInString("&")

    guard let encodedString = self.stringByAddingPercentEncodingWithAllowedCharacters(characters) else {
      return nil
    }

    return encodedString

  }

}
Run Code Online (Sandbox Code Playgroud)

  • @AlecThomas你似乎不得不跳过几个篮球来到这里,这就是为什么最好把它隐藏在一个扩展中 (2认同)

Und*_*dog 14

ios 7更新

NSString *encode = [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];

NSString *decode = [encode stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
Run Code Online (Sandbox Code Playgroud)


Mik*_*ell 8

我选择使用CFURLCreateStringByAddingPercentEscapes接受的答案给出的调用,但是在最新版本的XCode(和IOS)中,它导致了错误,因此使用以下代码:

NSString *apiKeyRaw = @"79b|7Qd.jW=])(fv|M&W0O|3CENnrbNh4}2E|-)J*BCjCMrWy%dSfGs#A6N38Fo~";

NSString *apiKey = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)apiKeyRaw, NULL, (CFStringRef)@"!*'();:@&=+$,/?%#[]", kCFStringEncodingUTF8));
Run Code Online (Sandbox Code Playgroud)

  • 对我来说,解决这个问题的大部分时间都是拒绝时期,我拒绝相信框架不包含类似于'urlencode'的东西,这样做没有乱七八糟的东西. (2认同)

Sup*_*tar 8

这是Swift 5.x 中一种可用于生产的灵活方法:

public extension CharacterSet {

    static let urlQueryParameterAllowed = CharacterSet.urlQueryAllowed.subtracting(CharacterSet(charactersIn: "&?"))

    static let urlQueryDenied           = CharacterSet.urlQueryAllowed.inverted()
    static let urlQueryKeyValueDenied   = CharacterSet.urlQueryParameterAllowed.inverted()
    static let urlPathDenied            = CharacterSet.urlPathAllowed.inverted()
    static let urlFragmentDenied        = CharacterSet.urlFragmentAllowed.inverted()
    static let urlHostDenied            = CharacterSet.urlHostAllowed.inverted()

    static let urlDenied                = CharacterSet.urlQueryDenied
        .union(.urlQueryKeyValueDenied)
        .union(.urlPathDenied)
        .union(.urlFragmentDenied)
        .union(.urlHostDenied)


    func inverted() -> CharacterSet {
        var copy = self
        copy.invert()
        return copy
    }
}



public extension String {
    func urlEncoded(denying deniedCharacters: CharacterSet = .urlDenied) -> String? {
        return addingPercentEncoding(withAllowedCharacters: deniedCharacters.inverted())
    }
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

print("Hello, World!".urlEncoded()!)
print("You&Me?".urlEncoded()!)
print("#Blessed 100%".urlEncoded()!)
print("Pride and Prejudice".urlEncoded(denying: .uppercaseLetters)!)
Run Code Online (Sandbox Code Playgroud)

输出:

print("Hello, World!".urlEncoded()!)
print("You&Me?".urlEncoded()!)
print("#Blessed 100%".urlEncoded()!)
print("Pride and Prejudice".urlEncoded(denying: .uppercaseLetters)!)
Run Code Online (Sandbox Code Playgroud)

  • 请发表评论,解释您投反对票的原因,以便我知道将来如何写出更好的答案 (3认同)

小智 7

此代码帮助我编码特殊字符

NSString* encPassword = [password stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]];
Run Code Online (Sandbox Code Playgroud)


Ale*_*lex 6

尝试使用它的stringByAddingPercentEncodingWithAllowedCharacters方法[NSCharacterSet URLUserAllowedCharacterSet]将涵盖所有情况

目标C.

NSString *value = @"Test / Test";
value = [value stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLUserAllowedCharacterSet]];
Run Code Online (Sandbox Code Playgroud)

迅速

var value = "Test / Test"
value.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLUserAllowedCharacterSet())
Run Code Online (Sandbox Code Playgroud)

产量

Test%20%2F%20Test


gab*_*bry 6

在阅读了该主题的所有答案和(错误的)已接受的答案后,我想添加我的贡献.

如果目标是iOS7 +,并且在2017年它应该因为XCode在iOS8下真正难以提供兼容性,最好的方式,线程安全,快速,amd将完全支持UTF-8支持:

(目标C代码)

@implementation NSString (NSString_urlencoding)

- (NSString *)urlencode {
    static NSMutableCharacterSet *chars = nil;
    static dispatch_once_t pred;

    if (chars)
        return [self stringByAddingPercentEncodingWithAllowedCharacters:chars];

    // to be thread safe
    dispatch_once(&pred, ^{
        chars = NSCharacterSet.URLQueryAllowedCharacterSet.mutableCopy;
        [chars removeCharactersInString:@"!*'();:@&=+$,/?%#[]"];
    });
    return [self stringByAddingPercentEncodingWithAllowedCharacters:chars];
}
@end
Run Code Online (Sandbox Code Playgroud)

这将扩展NSString,将排除RFC禁止字符,支持UTF-8字符,并允许您使用以下内容:

NSString *myusername = "I'm[evil]&want(to)break!!!$->àéìòù";
NSLog(@"Source: %@ -> Dest: %@", myusername, [myusername urlencode]);
Run Code Online (Sandbox Code Playgroud)

这将在您的调试控制台上打印:

资料来源:我[邪恶]想要(打破)!!! $ - >àéìòù - >目的地:I%27m%5Bevil%5D%26want%28to%29break%21%21%21%24%3E%C3 %A0%C3%A9%C3%AC%C3%B2%C3%B9

...还要注意使用dispatch_once来避免多线程环境中的多次初始化.


nit*_*tha 5

Apple 在 10.11 发行说明中的​​建议是:

如果您需要对整个 URL 字符串进行百分比编码,您可以使用此代码对旨在成为 URL 的 NSString 进行编码(在 urlStringToEncode 中):

NSString *percentEncodedURLString =
  [[NSURL URLWithDataRepresentation:[urlStringToEncode dataUsingEncoding:NSUTF8StringEncoding] relativeToURL:nil] relativeString];
Run Code Online (Sandbox Code Playgroud)