Objective-C的iPhone百分比编码一个string?
我想获得这些特定字母的百分比编码string,如何在objective-c中做到这一点?
Reserved characters after percent-encoding ! * ' ( ) ; : @ & = + $ , / ? # [ ] %21 %2A %27 %28 %29 %3B %3A %40 %26 %3D %2B %24 %2C %2F %3F %23 %5B %5D
编码百分比的wiki
请testing这个string,看看它是否工作:
myURL = @"someurl/somecontent"
我想这个string看起来像:
myEncodedURL = @"someurl%2Fsomecontent"
我尝试过使用stringByAddingPercentEscapesUsingEncoding: NSASCIIStringEncoding
但它不起作用,结果仍然是原来的string。 请指教。
我发现stringByAddingPercentEscapesUsingEncoding:
和CFURLCreateStringByAddingPercentEscapes()
是不够的。 NSString
方法错过了很多字符,而CF函数只能让你说出你想要转义哪些(特定的)字符。 正确的规格是逃避除了一个小集合以外的所有字符。
为了解决这个问题,我创build了一个NSString
类别方法来正确编码一个string。 除了[a-zA-Z0-9.-_~]
,它将编码所有内容的百分比,还将把空格编码为+
(根据此规范 )。 它也将正确处理编码unicode字符。
- (NSString *) URLEncodedString_ch { 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; }
iOS 7 SDK现在有了一个比stringByAddingPercentEscapesUsingEncoding
更好的替代方法,它可以让你指定除了某些允许的字符之外,所有的字符都被转义。 如果你正在build立部分的url,那么效果很好:
NSString * unescapedQuery = [[NSString alloc] initWithFormat:@"?myparam=%d", numericParamValue]; NSString * escapedQuery = [unescapedQuery stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; NSString * urlString = [[NSString alloc] initWithFormat:@"http://ExampleOnly.com/path.ext%@", escapedQuery];
虽然URL的其他部分不太可能是variables,但在NSURLUtilities类别中也有一些常量:
[NSCharacterSet URLHostAllowedCharacterSet] [NSCharacterSet URLUserAllowedCharacterSet] [NSCharacterSet URLPasswordAllowedCharacterSet] [NSCharacterSet URLPathAllowedCharacterSet] [NSCharacterSet URLFragmentAllowedCharacterSet]
[NSCharacterSet URLQueryAllowedCharacterSet]
包含URL查询部分允许的所有字符(以?
开始的部分以及#
之前的部分,如果有的话),包括?
以及用于分隔参数名称和值的&
或=
字符。 对于包含字母数字值的查询参数,这些字符中的任何字符都可能包含在用于构build查询string的variables的值中。 在这种情况下,查询string的每个部分都需要被转义,这只需要更多的工作:
NSMutableCharacterSet * URLQueryPartAllowedCharacterSet; // possibly defined in class extension ... // ... and built in init or on first use URLQueryPartAllowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy]; [URLQueryPartAllowedCharacterSet removeCharactersInString:@"&+=?"]; // %26, %3D, %3F // then escape variables in the URL, such as values in the query and any fragment: NSString * escapedValue = [anUnescapedValue stringByAddingPercentEncodingWithAllowedCharacters:URLQueryPartAllowedCharacterSet]; NSString * escapedFrag = [anUnescapedFrag stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]]; NSString * urlString = [[NSString alloc] initWithFormat:@"http://ExampleOnly.com/path.ext?myparam=%@#%@", escapedValue, escapedFrag]; NSURL * url = [[NSURL alloc] initWithString:urlString];
unescapedValue
甚至可以是整个URL,例如callback或redirect:
NSString * escapedCallbackParamValue = [anAlreadyEscapedCallbackURL stringByAddingPercentEncodingWithAllowedCharacters:URLQueryPartAllowedCharacterSet]; NSURL * callbackURL = [[NSURL alloc] initWithString:[[NSString alloc] initWithFormat:@"http://ExampleOnly.com/path.ext?callback=%@", escapedCallbackParamValue]];
注意:不要使用NSURL initWithScheme:(NSString *)scheme host:(NSString *)host path:(NSString *)path
具有查询string的URL NSURL initWithScheme:(NSString *)scheme host:(NSString *)host path:(NSString *)path
,因为它将向path添加更多百分比的转义。
NSString *encodedString = [myString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
它不会replace你的内联string; 它会返回一个新的string。 这意味着方法以“string”开始。 这是基于当前NSString实例化NSString的新实例的一种便捷方法。
注意 – 新的string会被autorelease
,所以当你完成它的时候不要调用release。
NSString的stringByAddingPercentEscapesUsingEncoding:看起来像你之后。
编辑 :这是一个使用CFURLCreateStringByAddingPercentEscapes
的例子。 originalString
可以是NSString
或CFStringRef
。
CFStringRef newString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, originalString, NULL, CFSTR("!*'();:@&=+@,/?#[]"), kCFStringEncodingUTF8);
请注意,这是未经testing。 您应该查看文档页面 ,以确保您了解CFStringRef
的内存分配语义,免费桥接的概念等等。
另外,我不知道(在我的头顶)在legalURLCharactersToBeEscaped
参数中指定的字符中的legalURLCharactersToBeEscaped
字符会被转义(由于在URL中是非法的)。 你可能想检查一下,虽然也许只是为了安全起见,直接指定你想要逃脱的字符。
我将这个答案作为一个社区维基,以便对CoreFoundation有更多了解的人可以改进。
如果您在您的objective-c程序中使用ASI HttpRequest库 ,那么我不能推荐它足够高,那么您可以在其ASIFormDataRequest对象上使用“encodeURL”助手API。 不幸的是,API不是静态的,所以也许值得在你的项目中使用它的实现来创build一个扩展。
直接从ASIFormDataRequest.m中为encodeURL实现复制的代码是:
- (NSString*)encodeURL:(NSString *)string { NSString *newString = NSMakeCollectable([(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, CFSTR(":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`"), CFStringConvertNSStringEncodingToEncoding([self stringEncoding])) autorelease]); if (newString) { return newString; } return @""; }
正如你所看到的,它基本上是CFURLCreateStringByAddingPercentEscapes
一个包装,它负责处理所有应该正确转义的字符。
遵循RFC3986标准,以下是我用于编码URL组件的内容:
// https://tools.ietf.org/html/rfc3986#section-2.2 let rfc3986Reserved = NSCharacterSet(charactersInString: "!*'();:@&=+$,/?#[]") let encoded = "email+with+plus@example.com".stringByAddingPercentEncodingWithAllowedCharacters(rfc3986Reserved.invertedSet)
输出: email%2Bwith%2Bplus%40example.com
在我注意到Rob的回答之前,似乎工作得很好,并且因为它更干净,所以我select了Dave的答案Swift。 我会把它留在这里,以防有人感兴趣:
public extension String { // For performance, I've replaced the char constants with integers, as char constants don't work in Swift. var URLEncodedValue: String { let output = NSMutableString() guard let source = self.cStringUsingEncoding(NSUTF8StringEncoding) else { return self } let sourceLen = source.count var i = 0 while i < sourceLen - 1 { let thisChar = source[i] if thisChar == 32 { output.appendString("+") } else if thisChar == 46 || thisChar == 45 || thisChar == 95 || thisChar == 126 || (thisChar >= 97 && thisChar <= 122) || (thisChar >= 65 && thisChar <= 90) || (thisChar >= 48 && thisChar <= 57) { output.appendFormat("%c", thisChar) } else { output.appendFormat("%%%02X", thisChar) } i++ } return output as String } }
在Swift4中:
var str = "someurl/somecontent" let percentEncodedString = str.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
- iPhone SDK与isKindOfClass和isMemberOfClass之间的区别
- 如何在Swift中设置UILabel的textColor
- applicationWillEnterForeground与applicationDidBecomeActive,applicationWillResignActive与applicationDidEnterBackground
- 如何在iOS中以编程方式创build和显示UISlider?
- AVAudioPlayer在debugging模式下抛出断点
- testingNSMutableArray是否包含一个string对象
- @selector中的参数
- 以编程方式检索iPhone上的内存使用情况
- 保持iPhonehibernate状态