在iOS 9中不推荐使用CFURLCreateStringByAddingPercentEscapes,如何使用“stringByAddingPercentEncodingWithAllowedCharacters”

时间:2016-03-04 08:07:00

标签: ios objective-c

我有以下代码:

    return (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, CFSTR(";:@&=+$,/?%#[]"), kCFStringEncodingUTF8);

Xcode表示它已在iOS 9中弃用。那么,我如何使用stringByAddingPercentEncodingWithAllowedCharacters?

谢谢!

3 个答案:

答案 0 :(得分:20)

试试这个

NSString *value = @"<url>";
value = [value stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];

答案 1 :(得分:11)

字符集URLQueryAllowedCharacterSet包含网址(..?key1=value1&key2=value2)的查询部分中允许的所有字符,并且不限于此类键和值中允许的字符数查询。例如。 URLQueryAllowedCharacterSet包含&+,因为这些在查询中是允许的(&分隔键/值对,+表示空格),但它们此类查询的不允许使用。

考虑以下代码:

NSString * key = "my&name";
NSString * value = "test+test";
NSString * safeKey= [key 
     stringByAddingPercentEncodingWithAllowedCharacters:
         [NSCharacterSet URLQueryAllowedCharacterSet]
];
NSString * safeValue= [value
     stringByAddingPercentEncodingWithAllowedCharacters:
         [NSCharacterSet URLQueryAllowedCharacterSet]
];
NSString * query = [NSString stringWithFormat:@"?%@=%@", safeKey, safeValue];

query将是?my&name=test+test,这是完全错误的。它定义了一个名为my且没有值的键和一个名为name的键,其值为test test(+表示空格!)。

正确的查询应为?my%26name=test%2Btest

只要您只处理ASCII字符串,或者只要服务器可以处理URL中的UTF-8字符(当今大多数Web服务器都这样做),您绝对必须编码的字符数实际上相当小并且非常稳定。试试那段代码:

NSCharacterSet * queryKVSet = [NSCharacterSet
    characterSetWithCharactersInString:":/?&=;+!@#$()',*% "
].invertedSet;

NSString * value = ...;
NSString * valueSafe = [value
    stringByAddingPercentEncodingWithAllowedCharacters:queryKVSet
];

答案 2 :(得分:3)

编码URLQueryAllowedCharacterSet中允许但在键或值中不允许的那些字符的另一种解决方案(例如:+):

- (NSString *)encodeByAddingPercentEscapes {
    NSMutableCharacterSet *charset = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
    [charset removeCharactersInString:@"!*'();:@&=+$,/?%#[]"];
    NSString *encodedValue = [self stringByAddingPercentEncodingWithAllowedCharacters:charset];
    return encodedValue;
}