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