我如何URL编码一个string

我有一个空格和&字符的URLstring( NSString )。 如何对整个string进行url编码(包括&符号字符和空格)?

不幸的是, stringByAddingPercentEscapesUsingEncoding并不总是100%的工作。 它对非URL字符进行编码,但只保留保留字符(如斜杠/和符号& )。 显然这是一个苹果知道的错误 ,但由于他们还没有解决这个问题,我一直在使用这个类别来对一个string进行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; } 

像这样使用:

 NSString *urlEncodedString = [@"SOME_URL_GOES_HERE" urlencode]; // Or, with an already existing string: NSString *someUrlString = @"someURL"; NSString *encodedUrlStr = [someUrlString urlencode]; 

这也适用:

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

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

Objective-C的iPhone百分比编码一个string?
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/

这可能会有所帮助

 NSString *sampleUrl = @"http://www.google.com/search.jsp?params=Java Developer"; NSString* encodedUrl = [sampleUrl stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; 

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

 NSString* encodedUrl = [sampleUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; 

您可以根据URL组件的要求select允许的字符集。

自答案被选定以来,新的API已被添加; 你现在可以使用NSURLUtilities。 由于URL的不同部分允许不同的字符,因此请使用适用的字符集。 下面的示例编码包含在查询string中:

 encodedString = [myString stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]; 

要专门转换“&”,您需要将其从url查询集中移除或使用其他url,因为url查询中允许使用“&”:

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

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 } } 

ios 7更新

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

我select使用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)); 

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

目标C

 NSString *value = @"Test / Test"; value = [value stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLUserAllowedCharacterSet]]; 

迅速

 var value = "Test / Test" value.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLUserAllowedCharacterSet()) 

产量

Test%20%2F%20Test

swift代码基于chown的objc答案在这个线程中。

 extension String { func urlEncode() -> String { return CFURLCreateStringByAddingPercentEscapes( nil, self, nil, "!*'();:@&=+$,/?%#[]", CFStringBuiltInEncodings.UTF8.rawValue ) } } 

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

如果目标是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 

这将扩展NSString,将排除RFC禁止的字符,支持UTF-8字符,并让你使用像这样的东西:

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

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

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

…还要注意使用dispatch_once来避免multithreading环境中的多重初始化。

使用NSURLComponents来编码HTTP GET参数:

  var urlComponents = NSURLComponents(string: "https://www.google.de/maps/")! urlComponents.queryItems = [ NSURLQueryItem(name: "q", value: String(51.500833)+","+String(-0.141944)), NSURLQueryItem(name: "z", value: String(6)) ] urlComponents.URL // returns https://www.google.de/maps/?q=51.500833,-0.141944&z=6 

http://www.ralfebert.de/snippets/ios/encoding-nsurl-get-parameters/

Swift 3中 ,请尝试以下内容:

 let stringURL = "YOUR URL TO BE ENCODE"; let encodedURLString = stringURL.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) print(encodedURLString) 

因为, stringByAddingPercentEscapesUsingEncoding非URL字符进行编码,但保留字符(如!*'();:@&=+$,/?%#[] ),您可以像下面的代码一样对url进行编码:

 let stringURL = "YOUR URL TO BE ENCODE"; let characterSetTobeAllowed = (CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[] ").inverted) if let encodedURLString = stringURL.addingPercentEncoding(withAllowedCharacters: characterSetTobeAllowed) { print(encodedURLString) } 
  -(NSString *)encodeUrlString:(NSString *)string { return CFBridgingRelease( CFURLCreateStringByAddingPercentEscapes( kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, CFSTR("!*'();:@&=+$,/?%#[]"), kCFStringEncodingUTF8) ); } 

根据以下博客

在我的情况下,最后一个组件是阿拉伯文字母我做了以下Swift 2.2

 extension String { func encodeUTF8() -> String? { //If I can create an NSURL out of the string nothing is wrong with it if let _ = NSURL(string: self) { return self } //Get the last component from the string this will return subSequence let optionalLastComponent = self.characters.split { $0 == "/" }.last if let lastComponent = optionalLastComponent { //Get the string from the sub sequence by mapping the characters to [String] then reduce the array to String let lastComponentAsString = lastComponent.map { String($0) }.reduce("", combine: +) //Get the range of the last component if let rangeOfLastComponent = self.rangeOfString(lastComponentAsString) { //Get the string without its last component let stringWithoutLastComponent = self.substringToIndex(rangeOfLastComponent.startIndex) //Encode the last component if let lastComponentEncoded = lastComponentAsString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.alphanumericCharacterSet()) { //Finally append the original string (without its last component) to the encoded part (encoded last component) let encodedString = stringWithoutLastComponent + lastComponentEncoded //Return the string (original string/encoded string) return encodedString } } } return nil; } } 

用法:

 let stringURL = "http://xxx.dev.com/endpoint/nonLatinCharacters" if let encodedStringURL = stringURL.encodeUTF8() { if let url = NSURL(string: encodedStringURL) { ... } } 

这段代码帮助我编码特殊字符

  NSString* encPassword = [password stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]]; 

对于单个www表单编码的查询参数,我在NSString上做了一个分类:

 - (NSString*)WWWFormEncoded{ NSMutableCharacterSet *chars = NSCharacterSet.alphanumericCharacterSet.mutableCopy; [chars addCharactersInString:@" "]; NSString* encodedString = [self stringByAddingPercentEncodingWithAllowedCharacters:chars]; encodedString = [encodedString stringByReplacingOccurrencesOfString:@" " withString:@"+"]; return encodedString; } 

//这是没有testing

 NSMutableCharacterSet* set = [[NSCharacterSet alphanumericCharacterSet] mutableCopy]; [set addCharactersInString:@"-_.~"]; NSString *encode = [test stringByAddingPercentEncodingWithAllowedCharacters:set]; 

我遇到了一个类似的问题,传递复杂的string作为POST参数。 我的string可以包含亚洲字符,空格,引号和各种特殊字符。 我最终find的解决scheme是将我的string转换为匹配的一系列unicode,例如使用[NSString stringWithFormat:@“Hu%04x”,[stringcharacterAtIndex:i]]从每个Unicode中获取Unicode,例如“Hu0040Hu0020Hu03f5 ….”原始string中的字符。 Java也可以做到这一点。

该string可以作为POST参数安全地传递。

在服务器端(PHP),我将所有“H”更改为“\”,并将结果string传递给json_decode。 最后一步是在将string存储到MySQL之前转义单引号。

这样我可以在我的服务器上存储任何UTF8string。

这个正在为我工​​作。

 func stringByAddingPercentEncodingForFormData(plusForSpace: Bool=false) -> String? { let unreserved = "*-._" let allowed = NSMutableCharacterSet.alphanumericCharacterSet() allowed.addCharactersInString(unreserved) if plusForSpace { allowed.addCharactersInString(" ") } var encoded = stringByAddingPercentEncodingWithAllowedCharacters(allowed) if plusForSpace { encoded = encoded?.stringByReplacingOccurrencesOfString(" ", withString: "+") } return encoded } 

我从这个链接find了上面的函数: http : //useyourloaf.com/blog/how-to-percent-encode-a-url-string/

您也可以使用这个function快速扩展。 请让我知道是否有任何问题。

在迅捷3:

 // exclude alpha and numeric == "full" encoding stringUrl = stringUrl.addingPercentEncoding(withAllowedCharacters: .alphanumerics)!; // exclude hostname and symbols &,/ and etc stringUrl = stringUrl.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!; 

Swift 4中提供了灵活的生产方法:

 public extension CharacterSet { public static let urlQueryParameterAllowed = CharacterSet.urlQueryAllowed.subtracting(CharacterSet(charactersIn: "&?")) public static let urlQueryDenied = CharacterSet.urlQueryAllowed.inverted() public static let urlQueryKeyValueDenied = CharacterSet.urlQueryParameterAllowed.inverted() public static let urlPathDenied = CharacterSet.urlPathAllowed.inverted() public static let urlFragmentDenied = CharacterSet.urlFragmentAllowed.inverted() public static let urlHostDenied = CharacterSet.urlHostAllowed.inverted() public static let urlDenied = CharacterSet.urlQueryDenied .union(.urlQueryKeyValueDenied) .union(.urlPathDenied) .union(.urlFragmentDenied) .union(.urlHostDenied) public 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()) } } 

用法示例:

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

输出:

 Hello,%20World! You%26Me%3F %23Blessed%20100%25 %50ride and %50rejudice 

苹果公司在10.11版本的build议中提出了如下build议:

如果您需要对整个URLstring进行百分比编码,则可以使用此代码对意图成为URL的url(在urlStringToEncode中)进行编码:

 NSString *percentEncodedURLString = [[NSURL URLWithDataRepresentation:[urlStringToEncode dataUsingEncoding:NSUTF8StringEncoding] relativeToURL:nil] relativeString];