AFNetworking源码阅读笔记(二)

二、Serialization的AFURLRequestSerialization部分

AFHTTPRequestSerializer是序列化器,主要功能是对传入的参数进行序列化。

在前一篇分析过,

其主要是通过构造request来实现其功能的,这里也将从这个入口开始,分析requestSerializer是如何构造这个NSMutableURLRequest  *request对象的。

在此之前先来看一下AFHTTPRequestSerializer的初始化方法:

AFNetworking源码阅读笔记(二)_第1张图片
AFNetworking源码阅读笔记(二)_第2张图片
AFNetworking源码阅读笔记(二)_第3张图片


AFNetworking源码阅读笔记(二)_第4张图片

表示返回一个默认配置的序列化器。

self.stringEncoding为编码方式,如果不做特别设置默认是UTF8。

self.mutableHTTPRequestHeaders为请求头构建的字典,self.requestHeaderModificationQueueself.mutableHTTPRequestHeaders的操作队列。

AFNetworking源码阅读笔记(二)_第5张图片
AFNetworking源码阅读笔记(二)_第6张图片

可以看得出对请求头字典的操作都在self.requestHeaderModificationQueue这个并发队列中进行。在获取请求头字典或是获取其中一个值时,

AFNetworking源码阅读笔记(二)_第7张图片
AFNetworking源码阅读笔记(二)_第8张图片

都使用同步添加任务

插入或移除条目时,

AFNetworking源码阅读笔记(二)_第9张图片
AFNetworking源码阅读笔记(二)_第10张图片

都使用了dispatch_barrier_async异步栅栏添加任务

AFNetworking源码阅读笔记(二)_第11张图片

[NSLocale  preferredLanguages]获取当前使用语言,参见详情1,参见详情2

这块就是向请求头中插入Accept-Language字段。

AFNetworking源码阅读笔记(二)_第12张图片
AFNetworking源码阅读笔记(二)_第13张图片

插入User-Agent字段,主要包含一些设备信息。

AFNetworking源码阅读笔记(二)_第14张图片

通过KVO添加对属性的观察,继续深入这个AFHTTPRequestSerializerObservedKeyPaths()函数:

AFNetworking源码阅读笔记(二)_第15张图片

可以看出是对着五个属性添加了属性观察,以timeoutInterval为例:

AFNetworking源码阅读笔记(二)_第16张图片

需要手动实现属性的 setter 方法,在设置操作的前后分别调用 willChangeValueForKey: 和 didChangeValueForKey方法,这两个方法用于通知系统该 key 的属性值即将和已经变更了;

下面开始具体分析这个request的构造方法:

AFNetworking源码阅读笔记(二)_第17张图片


AFNetworking源码阅读笔记(二)_第18张图片

系统方法创建NSMutableURLRequest *mutableRequest,并赋值urlHTTPMethod

AFNetworking源码阅读笔记(二)_第19张图片

存储观察属性的相关值。

下面重点分析这个方法:

AFNetworking源码阅读笔记(二)_第20张图片
AFNetworking源码阅读笔记(二)_第21张图片
AFNetworking源码阅读笔记(二)_第22张图片

self.HTTPRequestHeaders的值赋给request,所以如果在发送请求时要设置或添加请求头信息,都可通过self.HTTPRequestHeaders来完成。

下面就是最重要一部分编码过程:

AFNetworking源码阅读笔记(二)_第23张图片

分析AFURLRequestSerialization默认编码过程:

AFNetworking源码阅读笔记(二)_第24张图片

再继续深入AFQueryStringPairsFromDictionary(parameters)这个方法:

下面可知AFQueryStringPairsFromDictionary方法只接受NSDictionary*类型参数列表。

AFNetworking源码阅读笔记(二)_第25张图片
AFNetworking源码阅读笔记(二)_第26张图片
AFNetworking源码阅读笔记(二)_第27张图片

构造一个空的数组以供后面使用,构造一个排序器,看的出是针对排序集合元素的description属性进行排序。

下面就是NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value)这个函数的核心部分,以参数为字典为例:

AFNetworking源码阅读笔记(二)_第28张图片

先对dictionaryallKeys按之前构造的排序器排序[dictionary.allKeys sortedArrayUsingDescriptors:@[sortDescriptor]],然后对排完序的数组进行遍历for(id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[sortDescriptor]]) {

在遍历过程中每一步中递归调用[mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSStringstringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)]。具体分析这个方法:nestedKeydictionary每个条目的key值,nestedValue为每个条目的value值,可知在第一次调这个方法时

传入的keynil,所以在递归调用这个方法时传入的key即为nestedKey,传入的value即为nestedValue,假设nestedValue不为字典、数组、集合对象,则走入

具体看一下AFQueryStringPair这个类及相关方法。

AFNetworking源码阅读笔记(二)_第29张图片

可知是一个参数条目的对象,pair表示是成对出现的fieldvalue组成的对象,这也符合一般情况下的网络请求参数格式。然后再加入方法起始时构造的mutableQueryStringComponents的数组中,当传进来的参数列表遍历结束后,返回一个由AFQueryStringPair*类型对象组成的数组。

这里是以一个常见格式的字典类型参数为例,其他参数列表类型同样。

接着返回到

AFNetworking源码阅读笔记(二)_第30张图片

这个方法里边,可看出

AFNetworking源码阅读笔记(二)_第31张图片

在这里对上一步返回的AFQueryStringPair*类型对象数组进行遍历,每一个对象调用[pair URLEncodedStringValue]编码方法。

AFNetworking源码阅读笔记(二)_第32张图片

可看出编码的核心方法是NSString * AFPercentEscapedStringFromString(NSString *string)

这个方法前源码中有一段注释文档

AFNetworking源码阅读笔记(二)_第33张图片

可参考这里

具体分析:

AFNetworking源码阅读笔记(二)_第34张图片
AFNetworking源码阅读笔记(二)_第35张图片
AFNetworking源码阅读笔记(二)_第36张图片

构造一个字符集allowedCharacterSet,除去kAFCharactersGeneralDelimitersToEncodekAFCharactersSubDelimitersToEncode包含的字符,allowedCharacterSet中为字符中允许的字符,否则要转译。

AFNetworking源码阅读笔记(二)_第37张图片

这块是对传入的参数string进行相关的UTF-8编码

allowedCharacterSet表示在编码中可以保留的字符,否则要转译。

参看详情

现在返回到

AFNetworking源码阅读笔记(二)_第38张图片

可知[pair URLEncodedStringValue]是对每一个AFQueryStringPair*类型pair对象进行编码,再回到这里

AFNetworking源码阅读笔记(二)_第39张图片

可知query = AFQueryStringFromParameters(parameters)方法便可得到相应的编码后的字符串,回到这里

AFNetworking源码阅读笔记(二)_第40张图片

继续往下走

AFNetworking源码阅读笔记(二)_第41张图片

之前不知道self.HTTPMethodsEncodingParametersInURI这是干啥的,到这里明白了,看看之前的代码

可看出,如果请求使用get方式则走到这里

AFNetworking源码阅读笔记(二)_第42张图片

设置mutableRequestURL值。

如果请求方式为post,则走到这里

AFNetworking源码阅读笔记(二)_第43张图片

意思是如果请求头没设置Content-Type,默认是application/x-www-form-urlencoded表单提交,然后[mutableRequest setHTTPBody:[querydataUsingEncoding:self.stringEncoding]]设置post请求的body体。

最终返回mutableRequest

最后返回到这个方法

AFNetworking源码阅读笔记(二)_第44张图片

一个NSMutableURLRequest *类型的request对象构造完成,可以提供给上篇文章的NSDataTask用以构造dataTask请求任务对象。

接下来简析一下AFURLRequestSerialization的整体面貌:

AFNetworking源码阅读笔记(二)_第45张图片

可看出这篇文章所着重分析的request对象构造方法是@protocol  AFURLRequestSerialization协议的方法。从AFURLRequestSerialization.h头文件可看出框架实现的序列化器有三种

AFHTTPRequestSerializer是最基础的类型遵守了AFURLRequestSerialization协议,AFJSONRequestSerializer用于json提交时使用,AFPropertyListRequestSerializer用于application/x-plist提交时使用,它们都单独实现了- (nullable NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request withParameters:(nullableid)parameters error:(NSError*_Nullable__autoreleasing*)error方法。本文主要分析的是AFHTTPRequestSerializer的实现方法,其他两种不再赘述。

你可能感兴趣的:(AFNetworking源码阅读笔记(二))