stringByAddingPercentEscapesUsingEncoding:
用这个方法进行转义,每个汉字将转成相应的unicode编码对应的3个%形式,还会转义一些特殊字符(比如空格会变成%20,#会变成%23,[会变成%5B等)。该方法现在已经被废弃,官方建议使用stringByAddingPercentEncodingWithAllowedCharacters:(下面会进行介绍)。
stringByAddingPercentEscapesUsingEncoding:的用法:
NSString *queryWord = @"[q q&";
NSString *escapedString = [queryWord stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@", escapedString);
打印结果为:%5Bq%20q&
可以发现空格和[都被转义了,但是&没有。
- (NSString *)stringByAddingPercentEncodingWithAllowedCharacters:(NSCharacterSet *)allowedCharacters的使用
这个方法是iOS7.0开始有的,这个方法会对字符串进行更彻底的转义,需要传递一个参数:这个参数是一个字符集(NSCharacterSet ),这个字符集的作用是在进行转义过程中,不会对这个字符集中包含的字符进行转义,使这个字符集中的字符保持原样。
NSCharacterSet的介绍
NSCharacterSet类似一个字符串处理工具,除了在URL转义中用到还可以用它来处理字符串。
NSCharacterSet的常用API:
/** 根据一个给定的字符串获取一个NSCharacterSet对象 */
+ (NSCharacterSet*)characterSetWithCharactersInString:(NSString*)aString;
/** 相反字符串限制 */
@property(readonly,copy)NSCharacterSet* invertedSet;
/** 常用快捷方法集合 (常用的,已满足大多数需求) */
@property (readonly, class, copy) NSCharacterSet *whitespaceCharacterSet //空格
@property (readonly, class, copy) NSCharacterSet *whitespaceAndNewlineCharacterSet //空格和换行符
@property (readonly, class, copy) NSCharacterSet *decimalDigitCharacterSet //0-9的数字
@property (readonly, class, copy) NSCharacterSet *letterCharacterSet //所有字母 + lowercaseLetterCharacterSet//小写字母
@property (readonly, class, copy) NSCharacterSet *uppercaseLetterCharacterSet //大写字母
@property (readonly, class, copy) NSCharacterSet *alphanumericCharacterSet //所有数字和字母(大小写不分)
@property (readonly, class, copy) NSCharacterSet *punctuationCharacterSet //标点符号
@property (readonly, class, copy) NSCharacterSet *newlineCharacterSet //换行
@property (class, readonly, copy) NSCharacterSet *URLQueryAllowedCharacterSet//URL中允许的字符的字符集。
上述属性使用了class修饰,直接用[NSCharacterSet whitespaceCharacterSet]就能获取空格字符串集
例子一:使用NSCharacterSet转义字符
转义除了空格之外的所有字符
NSString *queryWord = @"[q q&";
NSCharacterSet *set = [NSCharacterSet whitespaceCharacterSet];
NSString *escapedString = [queryWord stringByAddingPercentEncodingWithAllowedCharacters:set];
NSLog(@"%@", escapedString);
打印结果为:%5B%71 %71%26可以发现除了空格之外的所有参数都被转义,字母也被转义了(这只是展示用法,实际参数转义的时候还是要视情况定)。
例子二:转义除了空格和字母之外的字符
NSString *queryWord = @"[q q&";
NSMutableCharacterSet *letterSet = [NSMutableCharacterSet letterCharacterSet];
[letterSet addCharactersInString:@" "];
NSString *escapedString = [queryWord stringByAddingPercentEncodingWithAllowedCharacters:letterSet];
NSLog(@"%@", escapedString);
打印结果为:%5Bq q%26
例子三:使用NSCharacterSet处理字符串
需求:把字符串中的数字和字符串分别截取出来,分成两个字符串
NSString *originalStr = @"qssq21233fd23j49fr034";
NSCharacterSet *numCharacterSet = [NSCharacterSet decimalDigitCharacterSet];//创建数字的字符串集
NSArray *letterArray = [originalStr componentsSeparatedByCharactersInSet:numCharacterSet];//把不在字符集中的字符分离成数组
NSString *letterStr = [letterArray componentsJoinedByString:@""];//把字符数组以空字符串拼成一个字符串
NSArray *numArray = [originalStr componentsSeparatedByCharactersInSet:[numCharacterSet invertedSet]];
NSString *numStr = [numArray componentsJoinedByString:@""];
NSLog(@"字母字符串:%@", letterStr);
NSLog(@"数字字符串:%@", numStr);
打印结果:字母字符串:qssqfdjfr
数字字符串:212332349034
AFNetworking中转义字符串的源码解析
NSString * AFPercentEscapedStringFromString(NSString *string) {
//定义两个字符串,这两个字符串中的字符还是需要转义的
static NSString * const kAFCharactersGeneralDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4
static NSString * const kAFCharactersSubDelimitersToEncode = @"!$&'()*+,;=";
//获取URL中允许的字符的字符集。
NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
//在URL中允许的字符的字符集中移除上面需要转义的字符集
[allowedCharacterSet removeCharactersInString:[kAFCharactersGeneralDelimitersToEncode stringByAppendingString:kAFCharactersSubDelimitersToEncode]];
// FIXME: https://github.com/AFNetworking/AFNetworking/pull/3028
// return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];
//以50个字符为单位截取字符串
static NSUInteger const batchSize = 50;
NSUInteger index = 0;
NSMutableString *escaped = @"".mutableCopy;
//最后一次字符的位置比字符串的长度小()即未转义完时继续转义
while (index < string.length) {
//获取剩余字符串长度和截取单位50的最小值,剩余长度大于50,先截取50个字符
NSUInteger length = MIN(string.length - index, batchSize);
NSRange range = NSMakeRange(index, length);
//像表情(👴🏻👮🏽),一个表情有多个字符,这个方法是为了防止表情或者汉字被截断
range = [string rangeOfComposedCharacterSequencesForRange:range];
NSString *substring = [string substringWithRange:range];
//转义allowedCharacterSet字符集外的字符
NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];
//把转义后的字符拼接到准备的可变字符串
[escaped appendString:encoded];
index += range.length;
}
return escaped;
}