AFNetworking 源码阅读笔记

508 阅读3分钟

##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);
}