iOS 7 SDK 现在有一个比stringByAddingPercentEscapesUsingEncoding 更好的替代方案,它可以让您指定您希望除某些允许的字符之外的所有字符进行转义。如果您要分段构建 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 的其他部分很少是变量,但 NSURLUtilities 类别中也有常量:
[NSCharacterSet URLHostAllowedCharacterSet]
[NSCharacterSet URLUserAllowedCharacterSet]
[NSCharacterSet URLPasswordAllowedCharacterSet]
[NSCharacterSet URLPathAllowedCharacterSet]
[NSCharacterSet URLFragmentAllowedCharacterSet]
[NSCharacterSet URLQueryAllowedCharacterSet] 包括 URL 的查询部分中允许的 所有 字符(以 ? 开头的部分,如果有片段,则在 # 之前),包括? 和& 或= 字符,用于分隔参数名称和值。对于具有字母数字值的查询参数,任何这些字符都可能包含在用于构建查询字符串的变量的值中。在这种情况下,查询字符串的每个 part 都需要转义,这需要更多的工作:
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,例如用于回调或重定向:
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 用于带有查询字符串的 URL,因为它会在路径中添加更多百分比转义。