##AFNetworking 源码阅读笔记
网络请求
####AFURLSessionManager
- 核心类 - 处理NSURLSession, 以及NSURLSession的回调
AFHTTPSessionManager
- AFURLSessionManager的子类, 封装了 GET, POST等方法.
###序列化
-
AFURLRequestSerialization请求协议
- AFHTTPSessionManager的中的AFHTTPRequestSerializer就是实现了该协议
- 递归调用AFQueryStringPairsFromKeyAndValue拿到所有参数之后放到一个数组里 遍历数组拼接&得到NSString
- HTTPMethodsEncodingParametersInURI属性可配置将哪一类请求的参数拼接在url上, 默认是GET,HEAD 和DELETE. 其他则放到body里.具体代码:
// HTTP Method Definitions; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html self.HTTPMethodsEncodingParametersInURI = [NSSet setWithObjects:@"GET", @"HEAD", @"DELETE", nil];和
if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) { if (query && query.length > 0) { mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]]; } } else { // #2864: an empty string is a valid x-www-form-urlencoded payload if (!query) { query = @""; } if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) { [mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; } [mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]]; -
AFURLResponseSerialization 响应协议
- AFHTTPSessionManager的中的AFHTTPResponseSerializer就是实现了该协议
- 移除 JSON 中的 null: AFJSONObjectByRemovingKeysWithNullValues
递归调用 移除null: 递归出口:[mutableDictionary removeObjectForKey:key];- 核心 - 这个方法根据在初始化方法中初始化的属性 acceptableContentTypes 和 acceptableStatusCodes 来判断当前响应是否有效
- (BOOL)validateResponse:(NSHTTPURLResponse *)response
data:(NSData *)data
error:(NSError * __autoreleasing *)error
{
BOOL responseIsValid = YES;
NSError *validationError = nil;
if (response && [response isKindOfClass:[NSHTTPURLResponse class]]) {
if (self.acceptableContentTypes && ![self.acceptableContentTypes containsObject:[response MIMEType]]) {
#1: 返回内容类型无效
}
if (self.acceptableStatusCodes && ![self.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode] && [response URL]) {
#2: 返回状态码无效
}
}
if (error && !responseIsValid) {
*error = validationError;
}
return responseIsValid;
}
###安全
- AFSecurityPolicy类封装了网络安全相关操作
- 核心:验证当前服务器是否被信任
[self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]
AFNetworking的主要流程:
- 由AFHTTPSessionManager发起post请求为例:
- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(nullable id)parameters
progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
1.通过AFHTTPSessionManager发起请求
AFHTTPSessionManager POST:parameters:progress:success:failure:
2. AFHTTPSessionManager通过requestSerializer,构建出request. 这里requestSerializer做了请求相关操作(构建请求头,请求体,请求格式application/json等)
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
3.将request作为参数,调用AFURLSessionManager的方法构建一个Task和该Task对应的AFURLSessionManagerTaskDelegate
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler {
// 对应iOS8以下 在并发创建task时候 小概率有同样的taskId的问题
__block NSURLSessionDataTask *dataTask = nil;
url_session_manager_create_task_safely(^{
dataTask = [self.session dataTaskWithRequest:request];
});
// 构建task对应的taskDelegate
[self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];
return dataTask;
}
3.1 AFURLSessionManagerTaskDelegate将传过来的各种block(uploadProgressBlock,downloadProgressBlock,completionHandler)保存在自身属性里.
- AFURLSessionManagerTaskDelegate主要是做回调相关处理 可以看到TaskDelegate相关属性
@interface AFURLSessionManagerTaskDelegate : NSObject <NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>
- (instancetype)initWithTask:(NSURLSessionTask *)task;
@property (nonatomic, weak) AFURLSessionManager *manager;
@property (nonatomic, strong) NSMutableData *mutableData;
@property (nonatomic, strong) NSProgress *uploadProgress;
@property (nonatomic, strong) NSProgress *downloadProgress;
@property (nonatomic, copy) NSURL *downloadFileURL;
@property (nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
@property (nonatomic, copy) AFURLSessionTaskProgressBlock uploadProgressBlock;
@property (nonatomic, copy) AFURLSessionTaskProgressBlock downloadProgressBlock;
@property (nonatomic, copy) AFURLSessionTaskCompletionHandler completionHandler;
@end
######3.2 将task和taskId对应起来 也就是存在AFURLSession的一个字典里 key是task.taskId. value是taskDelegate
- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
forTask:(NSURLSessionTask *)task
{
NSParameterAssert(task);
NSParameterAssert(delegate);
[self.lock lock];
self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
[self addNotificationObserverForTask:task];
[self.lock unlock];
}
4. 发起请求
到这里这个请求已经准备好了.调用resume走起~~~
[dataTask resume];
5.拿到响应结果,交给taskDelegate
- 服务端响应的结果,会通过系统提供的NSURLSession的回调方法传给我们
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
// 根据taskId找到对应的taskDelegate 还记得吗 taskDelegate里存有我们的各种block, 包括completeHandler
AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
// delegate may be nil when completing a task in the background
if (delegate) {
// 调用delegate对应的同名方法处理结果
[delegate URLSession:session task:task didCompleteWithError:error];
// 已经回调出去了,相当于这次处理结束了. 在字典中释放task和taskDelegate
[self removeDelegateForTask:task];
}
if (self.taskDidComplete) {
self.taskDidComplete(session, task, error);
}
}
6. 在TaskDelegate中处理响应
- 这里同样通过responseSerializer构建响应
responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];
- 将结果通过completionHandler回调出去
if (self.completionHandler) {
self.completionHandler(task.response, responseObject, serializationError);
}