Pre
- AFNetworking分析版本:4.0.1
结构图

- 所有ResponseSerializer都实现了
AFURLResponseSerialization协议
- (nullable id)responseObjectForResponse:(nullable NSURLResponse *)response
data:(nullable NSData *)data
error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW;
- 序列化类父类
AFHTTPResponseSerializer
@interface AFHTTPResponseSerializer : NSObject <AFURLResponseSerialization>
- (instancetype)init;
+ (instancetype)serializer;
@property (nonatomic, copy, nullable) NSIndexSet *acceptableStatusCodes;
@property (nonatomic, copy, nullable) NSSet <NSString *> *acceptableContentTypes;
- (BOOL)validateResponse:(nullable NSHTTPURLResponse *)response
data:(nullable NSData *)data
error:(NSError * _Nullable __autoreleasing *)error;
@end
AFJSONResponseSerializer,AFXMLParseResponseSerializer等类都继承自AFHTTPResponseSerializer,由于AF中的HTTP请求的reponseSerializer默认为AFJSONResponseSerializer,我们再来看一下AFJSONResponseSerializer的接口
@interface AFJSONResponseSerializer : AFHTTPResponseSerializer
- (instancetype)init;
@property (nonatomic, assign) NSJSONReadingOptions readingOptions;
@property (nonatomic, assign) BOOL removesKeysWithNullValues;
+ (instancetype)serializerWithReadingOptions:(NSJSONReadingOptions)readingOptions;
@end
在其初始化方法中,设置了可接受的content type为"application/json", "text/json","text/javascript"
调用流程
- 入口:在之前文章中分析的封装请求过程中,会为当前的
task对象添加一个AFURLSessionManagerTaskDelegate代理,它实现了NSURLSessionTaskDelegate协议,并实现了以下方法。也就是说我们收到的response会来到AFURLSessionManager的这个方法中。
- (void)URLSession:(__unused NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error;
断点也可以证明确实走到了这里。 
- 根据当前task获取到对应的delegate
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
/* delegateForTask:实现
* 用之前分析过的task的identifier获取
*/
delegate = self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)];
- 若
delegate不为空(若task在后台完成,delegate可能为空
- 2.1 调用
delegate的URLSession: task:didCompleteWithError:方法
[delegate URLSession:session task:task didCompleteWithError:error];
- 2.2 移除该
task的delegate及notification
- 若当前manager设置过
taskDidComplete,调用该block
if (self.taskDidComplete) {
self.taskDidComplete(session, task, error);
}
delegate处理详解
- 断点可以看到,走到时,该delegate类型为
AFURLSessionManagerTaskDelegate
我们来进入该delegate的URLSession: task:didCompleteWithError:方法看看
获取部分数据存入字典userInfo
- 该字典是一个局部变量,名为
userInfo,可能有的key值为
- 以
AuthenticationChallengeErrorKey为key获取task关联对象error,若为空则error仍为传进来的上层error(对不起这边还不太懂)
error = objc_getAssociatedObject(task, AuthenticationChallengeErrorKey) ?: error;
- 强引用获取
manager,因为在delegate中对manager是弱引用,防止其被提前释放 - 若本delegate的
mutableData不为空,获取一份copy值data并将原属性值释放(因为再也用不着了)
if (self.mutableData) {
data = [self.mutableData copy];
//We no longer need the reference, so nil it out to gain back some memory.
self.mutableData = nil;
}
ps.self.mutableData数据来自于NSURLSessionDataTaskDelegate如下的回调方法接收获得:
- (void)URLSession:(__unused NSURLSession *)session
dataTask:(__unused NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data{
[self.mutableData appendData:data];
}
- 将本delegate的
sessionTaskMetrics(若不为空)存入字典 - 将
downloadFileURL或data(若不为空)存入字典
若出现error
- 以
AFNetworkingTaskDidCompleteErrorKey为key将error存入字典 - 判断是否指定过本
manager的completionGroup和completionQueue,若有则使用,若无则使用创建的一个url_session_manager_completion_group调度组/主队列执行:
2.1 异步调用completionHandler:block处理response和error
2.2 主队列上异步(避免阻塞主队列的其他任务执行)发送AFNetworkingTaskDidCompleteNotification通知(可以进行UI相关处理)
若无error(获取到正常的response)
- 创建一个并发队列并执行
- 调用本
manager的responseSerializer对接收到的task的response进行有效性验证。
responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];
- 若
self.downloadFileURL不为空,赋值给responseObject
- 什么情况不为空
- 若序列化后的
responseObject不为空,存入字典 - 若序列化出错,将
error传入字典 - 同【若出现error 第2步】
responseSerializer详解
- 根据文首的结构图我们可以看到,
responseSerializer可能为AFHTTPResponseSerializer(父),也可能为AFJSONResponseSerializer(子),AFXMLParserResponseSerializer(子)等类型。若调用者未设置,默认为AFJSONResponseSerializer类型,此处分析AFHTTPResponseSerializer和AFJSONResponseSerializer对response的序列化解析流程,即responseObjectForResponse:data:error:方法。
AFHTTPResponseSerializer
- 验证
response的有效性,返回data(即上层的responseObject)和error - 此处解析
AFHTTPResponseSerializer的validateResponse:data:error:方法
- 若返回内容类型无效/无法解析
- 即
acceptableContentTypes不不包含response的MIMEType - 封装错误类型(
AFURLResponseSerializationErrorDomain)
- 即
NSMutableDictionary *mutableUserInfo = [@{
NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: unacceptable content-type: %@", @"AFNetworking", nil), [response MIMEType]],
NSURLErrorFailingURLErrorKey:[response URL],
AFNetworkingOperationFailingURLResponseErrorKey: response,
} mutableCopy];
- 若返回的状态码无效
- 即
acceptableStatusCodes不包含response的状态码 - 封装错误类型(
AFURLResponseSerializationErrorDomain)
- 即
NSMutableDictionary *mutableUserInfo = [@{
NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: %@ (%ld)", @"AFNetworking", nil), [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], (long)response.statusCode],
NSURLErrorFailingURLErrorKey:[response URL],
AFNetworkingOperationFailingURLResponseErrorKey: response,
} mutableCopy];
AFJSONResponseSerializer
- 调用父类
AFHTTPResponseSerializer的validateResponse:data:error:方法对返回内容有效性进行判断,若无效则返回nil - 排除是否为一个空格(一个safari的bug)或为空的数据
BOOL isSpace = [data isEqualToData:[NSData dataWithBytes:" " length:1]];
- 调用
NSJSONSerialization的JSONObjectWithData方法解析data - 若
self.removesKeysWithNullValues属性值设置为YES (默认为NO),移除解析后的responseObject(JSON)中的空值
if (self.removesKeysWithNullValues) {
return AFJSONObjectByRemovingKeysWithNullValues(responseObject, self.readingOptions);
}
a. 若responseObject为NSArray类型
- 创建可变数组
- 递归遍历responseObject向数组中添加元素
- 返回数组
b. 若responseObject为NSDictionary类型
- 用responseObject创建可变字典
- 遍历responseObject中所有key值
- 若value为空,移除;若为数组,递归;若为字典;递归
- 返回字典
来源:oschina
链接:https://my.oschina.net/u/4135139/blog/4951160
我们来进入该delegate的