目录结构
-
NSURLSession
这个目录是封装了http请求需要的代码,其中AFURLSessionManager类主要处理http请求,AFHTTPSessionManager类是对其进行封装留给用户调用的上层接口。比如我们平时的get,post请求就要用到该类,也是本文要分析的重点。 -
Reachability
这个目录是判断网络状态的 -
Security
https请求 -
Serialization
http请求和相应的配置 -
UIKit
分类
post请求过程
第一步:用户创建单例
+ (instancetype)shareManager{ static dispatch_once_t token; static HttpClientManager *instance = nil; _dispatch_once(&token, ^{ instance = [[self alloc] init]; [instance initSession]; }); return instance;}- (void)initSession{ _sessionManger = [AFHTTPSessionManager manager]; _sessionManger.requestSerializer = [AFJSONRequestSerializer serializer];//请求配置 AFJSONResponseSerializer *response = [AFJSONResponseSerializer serializer];//相应配置 response.removesKeysWithNullValues = YES;//当出现null值时候移除该键值对 _sessionManger.responseSerializer = response; _sessionManger.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/json", @"text/plain", @"text/html", nil];//相应配置 _baseUrl = @"http:xxxxx/";//协议+域名+端口号(请求前缀)}复制代码
[AFHTTPSessionManager manager]查看源代码发现接下来调用一下代码
//1.(AFHTTPSessionManager类)+ (instancetype)manager { return [[[self class] alloc] initWithBaseURL:nil];}//2.(AFHTTPSessionManager类)- (instancetype)initWithBaseURL:(NSURL *)url { return [self initWithBaseURL:url sessionConfiguration:nil];}//3.(AFHTTPSessionManager类)- (instancetype)initWithBaseURL:(NSURL *)url sessionConfiguration:(NSURLSessionConfiguration *)configuration{ self = [super initWithSessionConfiguration:configuration];//分析父类 if (!self) { return nil; } // Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) { url = [url URLByAppendingPathComponent:@""]; } self.baseURL = url; self.requestSerializer = [AFHTTPRequestSerializer serializer]; self.responseSerializer = [AFJSONResponseSerializer serializer]; return self;}//4.(AFURLSessionManager类)- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration { self = [super init]; if (!self) { return nil; } if (!configuration) { configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; } self.sessionConfiguration = configuration; self.operationQueue = [[NSOperationQueue alloc] init]; self.operationQueue.maxConcurrentOperationCount = 1; self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];//注意delegate = self,也就是说网络请求的结果在AFURLSessionManager类里 self.responseSerializer = [AFJSONResponseSerializer serializer]; self.securityPolicy = [AFSecurityPolicy defaultPolicy];#if !TARGET_OS_WATCH self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];#endif self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init]; self.lock = [[NSLock alloc] init]; self.lock.name = AFURLSessionManagerLockName; [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) { for (NSURLSessionDataTask *task in dataTasks) { [self addDelegateForDataTask:task uploadProgress:nil downloadProgress:nil completionHandler:nil]; } for (NSURLSessionUploadTask *uploadTask in uploadTasks) { [self addDelegateForUploadTask:uploadTask progress:nil completionHandler:nil]; } for (NSURLSessionDownloadTask *downloadTask in downloadTasks) { [self addDelegateForDownloadTask:downloadTask progress:nil destination:nil completionHandler:nil]; } }]; return self;}复制代码
已上是AFHTTPSessionManager初始化的分析
第二步:用户开始调用post方法
[_sessionManger POST:urlString parameters:dicM progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { //请求成功 } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { //error包含HTTP请求的错误码,或者NSURLError错误码(-1001,-1009等等) }];复制代码
查看源代码调用过程如下
1.(AFHTTPSessionManager类)- (NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(id)parameters progress:(void (^)(NSProgress * _Nonnull))uploadProgress success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure{ NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters uploadProgress:uploadProgress downloadProgress:nil success:success failure:failure];//分析源代码(回调已经向下传递) [dataTask resume]; return dataTask;}2.(AFHTTPSessionManager类)- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method URLString:(NSString *)URLString parameters:(id)parameters uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress success:(void (^)(NSURLSessionDataTask *, id))success failure:(void (^)(NSURLSessionDataTask *, NSError *))failure{ NSError *serializationError = nil; NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];//请求配置 if (serializationError) { if (failure) { dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ failure(nil, serializationError);//请求配置失败 }); } return nil; } __block NSURLSessionDataTask *dataTask = nil; //以下创建dataTask(向下分析源代码) dataTask = [self dataTaskWithRequest:request uploadProgress:uploadProgress downloadProgress:downloadProgress completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { //回调(最上层的回调要执行那么就必须该completionHandler回调必须执行,也就是说completionHandler回调执行与否决定最上层的回调是否执行。我们只要关心completionHandler回调即可) if (error) { if (failure) { failure(dataTask, error); } } else { if (success) { success(dataTask, responseObject); } } }]; return dataTask;//返回dataTask}//3.(AFURLSessionManager类)- (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 { __block NSURLSessionDataTask *dataTask = nil; url_session_manager_create_task_safely(^{ //创建dataTask dataTask = [self.session dataTaskWithRequest:request]; }); //addDelegate(completionHandler向下传递),向下分析源代码 [self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler]; return dataTask;}//4.(AFURLSessionManager类)- (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTask uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler{ AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:dataTask]; delegate.manager = self; //将回调保存到AFURLSessionManagerTaskDelegate对象里 delegate.completionHandler = completionHandler; dataTask.taskDescription = self.taskDescriptionForSessionTasks; //传入delegate对象,dataTask(向下分析源代码) [self setDelegate:delegate forTask:dataTask]; delegate.uploadProgressBlock = uploadProgressBlock; delegate.downloadProgressBlock = downloadProgressBlock;}//5.(AFURLSessionManager类)- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate forTask:(NSURLSessionTask *)task{ NSParameterAssert(task); NSParameterAssert(delegate); //避免多线程访问mutableTaskDelegatesKeyedByTaskIdentifier字典 [self.lock lock]; //将AFURLSessionManagerTaskDelegate对象存储在 //mutableTaskDelegatesKeyedByTaskIdentifier字典里 //AFURLSessionManagerTaskDelegate对象里边存着回调,现在又将该对象存在字典里。并以task.taskIdentifier为key self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate; [self addNotificationObserverForTask:task]; [self.lock unlock];}复制代码
经过以上分析知道最后将回调保存在了mutableTaskDelegatesKeyedByTaskIdentifier这个字典里的AFURLSessionManagerTaskDelegate对象中。
然后经过resume后,开始发起post请求。请求的结果回调在AFURLSessionManager类中(上面初始化代码可知)。第三步:请求结果回调
找到AFURLSessionManager类下的网络请求结果代理方法
//1. (AFURLSessionManager类)- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)taskdidCompleteWithError:(NSError *)error{ //获取该task对应的AFURLSessionManagerTaskDelegate对象,实际上就是从字典中取值(分析源代码) AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task]; // delegate may be nil when completing a task in the background if (delegate) { //调用AFURLSessionManagerTaskDelegate对象中的URLSession: task: didCompleteWithError:方法(分析源代码) [delegate URLSession:session task:task didCompleteWithError:error]; //移除task,实际上是从字典中移除(分析源代码) [self removeDelegateForTask:task]; } //完成回调,其实这里我们没用到,所以不会进入 if (self.taskDidComplete) { self.taskDidComplete(session, task, error); }}//2.(AFURLSessionManager类)- (AFURLSessionManagerTaskDelegate *)delegateForTask:(NSURLSessionTask *)task { NSParameterAssert(task); AFURLSessionManagerTaskDelegate *delegate = nil; [self.lock lock]; //根据task.taskIdentifier获取字典中的AFURLSessionManagerTaskDelegate对象 delegate = self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)]; [self.lock unlock]; return delegate;}//3. (AFURLSessionManager类)- (void)removeDelegateForTask:(NSURLSessionTask *)task { NSParameterAssert(task); [self.lock lock]; [self removeNotificationObserverForTask:task]; //从字典中移除task.taskIdentifier对应的AFURLSessionManagerTaskDelegate对象 [self.mutableTaskDelegatesKeyedByTaskIdentifier removeObjectForKey:@(task.taskIdentifier)]; [self.lock unlock];}//4.(AFURLSessionManagerTaskDelegate类)- (void)URLSession:(__unused NSURLSession *)session task:(NSURLSessionTask *)taskdidCompleteWithError:(NSError *)error{ __strong AFURLSessionManager *manager = self.manager; __block id responseObject = nil; //创建空字典userInfo __block NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; //userInfo保存responseSerializer userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer; //Performance Improvement from #2672 //获取data NSData *data = nil; 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; } if (self.downloadFileURL) { //userInfo保存downloadFileURL userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL; } else if (data) { //userInfo保存data userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data; } if (error) { //有错误 //userInfo保存error userInfo[AFNetworkingTaskDidCompleteErrorKey] = error; dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{ //如果没有定义队列就在主队列回调 if (self.completionHandler) { //self是AFURLSessionManagerTaskDelegate对象,经过以上分析,该对象中的completionHandler回调,即可触发上层回调 self.completionHandler(task.response, responseObject, error); } dispatch_async(dispatch_get_main_queue(), ^{ //发送通知,将userInfo发出 [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo]; }); }); } else { //请求成功 dispatch_async(url_session_manager_processing_queue(), ^{ //定义serializationError NSError *serializationError = nil; //data解析为json对象 responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError]; if (self.downloadFileURL) { //responseObject赋值 responseObject = self.downloadFileURL; } if (responseObject) { //userInfo保存responseObject userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject; } if (serializationError) { //userInfo保存serializationError userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError; } dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{ //如果没有定义回调队列,就在主队列回调 if (self.completionHandler) { //self是AFURLSessionManagerTaskDelegate对象,经过以上分析,该对象中的completionHandler回调,即可触发上层回调 self.completionHandler(task.response, responseObject, serializationError); } dispatch_async(dispatch_get_main_queue(), ^{ //发送通知,将userInfo发出 [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo]; }); }); }); }}复制代码
AFN请求过程梳理
首先我们是初始化了AFHTTPSessionManager类(往往创建单例)初始化时候指定请求回调的代理是父类(AFURLSessionManager)。之后当我们发出一个请求后,先创建一个AFURLSessionManagerTaskDelegate对象来保存请求结果回调。并把该对象放到一个全局字典中来保存(以task.taskIdentifier为key),再启动请求。当AFURLSessionManager类收到了请求结果后根据task.taskIdentifier从全局字典中取出当前请求的AFURLSessionManagerTaskDelegate对象。然后调用AFURLSessionManagerTaskDelegate的对象方法处理请求,完成回调。之后再从全局字典中移除该AFURLSessionManagerTaskDelegate对象。
AFN是怎样来解决循环引用的
首先我们用AFN时候往往是用单例,因此调用类不会直接持有该AFHTTPSessionManager对象。
该AFHTTPSessionManager对象持有block,该AFHTTPSessionManager对象持有全局字典,该全局字典持有AFURLSessionManagerTaskDelegate对象,该AFURLSessionManagerTaskDelegate对象持有block,这是一个循环引用。
当AFURLSessionManagerTaskDelegate对象block进行回调后,从全局字典中移除该对象。从而打破引用环。