AFNetworking3.1.0源码分析(三)AFHTTPRequestSerializer 之AFQueryStringPair
来源:互联网 发布:精算师所需软件 编辑:程序博客网 时间:2024/06/05 18:21
介绍
在发送请求之前需要配置request的各项参数,比如请求内容的编码,AFNetWorking中使用AFQueryStringPair类用来对网络请求数据进行编码(百分号编码)遵循rfc3986,
AFQueryStringPair类通过函数NSString * AFPercentEscapedStringFromString(NSString *string){}实现编码。
预备知识:
1:URL理编码:
URL理编码时(使用%编码)默认根据ASCII国际标准(0-127范围)根据分析iOS CFURL源码(https://opensource.apple.com/source/CF/CF-855.14/)可以看到static const unsigned char sURLValidCharacters[128] 变量,存放了系统允许的字符集。
2:对于URL字符集的支持,根据系统函数
[NSCharacterSet URLUserAllowedCharacterSet]
[NSCharacterSet URLHostAllowedCharacterSet]
[NSCharacterSet URLPasswordAllowedCharacterSet]
[NSCharacterSet URLPathAllowedCharacterSet]
[NSCharacterSet URLQueryAllowedCharacterSet]
[NSCharacterSet URLFragmentAllowedCharacterSet]
函数获得,获取出来的是一个NSCharacterSet 对象,系统未开放API显示字符集,我通过循环遍历0-127之间的字符是否存在当前的字符集对象中,整理出以下系统对URL 不同segment支持的字符集,拿URLQueryAllowedCharacterSet举例:
NSMutableCharacterSet * URLQueryAllowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy]; NSMutableArray *URLQueryAllowedCharacters = [NSMutableArray arrayWithCapacity:0]; for (int i = 0; i < 128; i++) { NSString *string =[NSString stringWithFormat:@"%c",i]; if ([string rangeOfCharacterFromSet:URLQueryAllowedCharacterSet].location != NSNotFound) { [URLQueryAllowedCharacters addObject:string]; }; } NSLog(@"allowedCharacters = %@\n\n",[URLQueryAllowedCharacters componentsJoinedByString:@" "]);其它的可以效仿上面的方式输出,最终所有的字符集输出如下:
2016-11-24 11:01:55.396 test2[1775:50836] -------------URLUserAllowedCharacterSet-------------2016-11-24 11:01:55.397 test2[1775:50836] allowedCharacters = ! $ & ' ( ) * + , - . 0 1 2 3 4 5 6 7 8 9 ; = A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z ~2016-11-24 11:01:55.398 test2[1775:50836] -------------URLPasswordAllowedCharacterSet-------------2016-11-24 11:01:55.399 test2[1775:50836] allowedCharacters = ! $ & ' ( ) * + , - . 0 1 2 3 4 5 6 7 8 9 ; = A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z ~2016-11-24 11:01:55.399 test2[1775:50836] -------------URLHostAllowedCharacterSet-------------2016-11-24 11:01:55.400 test2[1775:50836] allowedCharacters = ! $ & ' ( ) * + , - . 0 1 2 3 4 5 6 7 8 9 : ; = A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ ] _ a b c d e f g h i j k l m n o p q r s t u v w x y z ~2016-11-24 11:01:55.400 test2[1775:50836] -------------URLPathAllowedCharacterSet-------------2016-11-24 11:01:55.401 test2[1775:50836] allowedCharacters = ! $ & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : = @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z ~2016-11-24 11:01:55.401 test2[1775:50836] -------------URLQueryAllowedCharacterSet-------------2016-11-24 11:01:55.402 test2[1775:50836] allowedCharacters = ! $ & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; = ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z ~2016-11-24 11:01:55.403 test2[1775:50836] -------------URLFragmentAllowedCharacterSet-------------2016-11-24 11:01:55.403 test2[1775:50836] allowedCharacters = ! $ & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; = ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z ~
AFNetWorking对URL编码实现
1:编码实现(此实现可以单独作为一个扩展实现使用到自己的项目中)
NSString * AFPercentEscapedStringFromString(NSString *string) { ① static NSString * const kAFCharactersGeneralDelimitersToEncode = @":#[]@"; ② static NSString * const kAFCharactersSubDelimitersToEncode = @"!$&'()*+,;="; ③ NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy]; ④ [allowedCharacterSet removeCharactersInString:[kAFCharactersGeneralDelimitersToEncode stringByAppendingString:kAFCharactersSubDelimitersToEncode]]; ⑤ // FIXME: https://github.com/AFNetworking/AFNetworking/pull/3028 // return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; static NSUInteger const batchSize = 50; NSUInteger index = 0; NSMutableString *escaped = @"".mutableCopy; while (index < string.length) { NSUInteger length = MIN(string.length - index, batchSize); ⑥ NSRange range = NSMakeRange(index, length); // To avoid breaking up character sequences such as range = [string rangeOfComposedCharacterSequencesForRange:range]; NSString *substring = [string substringWithRange:range]; NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet]; [escaped appendString:encoded]; ⑦ index += range.length; } return escaped;}解释:
①和②根据rfc3986创建在URI中query部分进行百分号编码的字符
③获取iOS系统针对URI中query部分允许出现的字符集
④根据rfc的规范去除①和②中出现的字符,得到最终的在query部分可以出现的字符集(不被百分号编码)
⑤介绍了一个关于系统直接编码产生的bug,因为在query中可能会出现emoji等特殊字符,这些字符的在编码过程中出现问题,具体的介绍往后看⑥-⑦的介绍
⑥-⑦:因为iOS系统的字符串编码默认使用utf16,中文字符的长度是1,实际上是占用两个字节,对于emoji (表情符号)等特殊字符,这些字符的长度是4,在对其编码的时候需要按位进行,如果只是简单的取出每一位的字符,就会产生断字。因此需要使用字符串的rangeOfComposedCharacterSequencesForRange: 方法达到整取的效果,比如某个字符串中有一个英文字符和3个表情符号,长度(length)应该是13,这时候取长度10,就只能取一个英文字符和连个表情字符,达到整取的效果,不会产生断字,影响到编码,此处代码中有个 batchSize 设置为50,是个默认值,这个地方你也可以这是10,或者100。主要是为了而快速的取值,算是一个策略值吧
- AFNetworking3.1.0源码分析(三)AFHTTPRequestSerializer 之AFQueryStringPair
- AFNetworking3.1.0源码分析(八)AFHTTPRequestSerializer 之AFStreamingMultipartFormData下
- AFNetworking3.1.0源码分析(四)详解AFHTTPRequestSerializer 之初始化方法
- AFNetworking3.1.0源码分析(五)详解AFHTTPRequestSerializer 之创建NSMutableURLRequest
- AFNetworking3.1.0源码分析(六)详解AFHTTPRequestSerializer 之序列化NSMutableURLRequest
- AFNetworking3.1.0源码分析(七)详解AFHTTPRequestSerializer 之AFStreamingMultipartFormData上
- AFNetworking3.1.0源码分析(九)AFHTTPRequestSerializer 之解决调用Amazon S3 服务出现的bug
- AFNetworking3.1.0源码分析(十)之AFSecurityPolicy
- AFNetworking3.1.0源码分析(十一)之AFSecurityPolicy验证服务器信任
- AFNetworking3.1.0源码分析(一)整体框架和功能模块
- AFNetworking3.0 源码阅读(三)
- AFNetworking3.1.0源码分析(十二)AFURLResponseSerialization
- AFNetworking3.1.0源码分析(十四)AFHTTPSessionManager
- AFNetworking3.1.0源码分析(十三)AFURLSessionManager
- AFNetworking3.0源码解读(一)之 AFNetworkReachabilityManager
- iOS 之 AFNetWorking3.1.0
- lguest 三步曲之三 (源码分析)
- Memcached源码分析之状态机(三)
- 【自研IM系统Talk00】 --- 集成接入&demo展示
- CoreAnimation6-基于定时器的动画和性能调优
- 对Map里的数据进行封装(数据类型和判空处理)
- is_base_of
- Android复制和粘贴的实现
- AFNetworking3.1.0源码分析(三)AFHTTPRequestSerializer 之AFQueryStringPair
- android动画
- Linux设备驱动第一天学习笔记(如何将系统在开发板上运行起来、驱动开发基本步骤)
- CorAnimation7-高效绘图、图像IO以及图层性能
- java微信第三方平台全网发布(三)
- bootstrap树状图
- C#反射机制总结
- 【Android源码学习】应用启动过程
- Weblogic配置集群以及使用命令开启子节点