AFURLSessionManager 和 AFHTTPSessionManager 是AFNetworking的核心类
 
使用 AFURLSessionManager 创建下载任务 1 2 3 4 5 6 7 8 9 10 11 12 13 NSURLSessionConfiguration  *configuration = [NSURLSessionConfiguration  defaultSessionConfiguration];AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration]; NSURL  *URL = [NSURL  URLWithString:@"http://example.com/download.zip" ];NSURLRequest  *request = [NSURLRequest  requestWithURL:URL];NSURLSessionDownloadTask  *downloadTask = [manager downloadTaskWithRequest:request progress:nil  destination:^NSURL  *(NSURL  *targetPath, NSURLResponse  *response) {    NSURL  *documentsDirectoryURL = [[NSFileManager  defaultManager] URLForDirectory:NSDocumentDirectory  inDomain:NSUserDomainMask  appropriateForURL:nil  create:NO  error:nil ];     return  [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]]; } completionHandler:^(NSURLResponse  *response, NSURL  *filePath, NSError  *error) {     NSLog (@"File downloaded to: %@" , filePath); }]; [downloadTask resume]; 
AFURLSessionManager 初始化 
initWithSessionConfiguration: 创建和管理 NSURLSession
 
1 2 3 4 - (instancetype )initWithSessionConfiguration:(NSURLSessionConfiguration  *)configuration{ 	1.  初始化相应的属性 	2.  为task设置代理 } 
1.  初始化相应的属性
初始化会话配置 (NSURLSessionConfiguration),默认为defaultSessionConfiguration  
初始化会话 (NSURLSession),设置会话的配置,代理以及队列 
初始化响应序列化 (AFJSONResponseSerializer),安全认证 (AFSecurityPolicy),网络状态监控 (AFNetworkReachabilityManager) 
初始化保存 data task 的字典(mutableTaskDelegatesKeyedByTaskIdentifier) 
 
2.  为task设置代理
使用getTasksWithCompletionHandler从session中取出task,并为task设置代理。
管理NSURLSessionTask 
AFURLSessionManager初始化后,就可以获取NSURLSessionTask对象
 
AFNetworking3 中有7个方法分别返回NSURLSessionDataTask,NSURLSessionUploadTask,NSURLSessionDownloadTask。这里从以下方法来看是如何实现的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 - (NSURLSessionUploadTask  *)uploadTaskWithRequest:(NSURLRequest  *)request                                          fromData:(NSData  *)bodyData                                          progress:(void  (^)(NSProgress  *uploadProgress)) uploadProgressBlock                                 completionHandler:(void  (^)(NSURLResponse  *response, id  responseObject, NSError  *error))completionHandler {     __block NSURLSessionUploadTask  *uploadTask = nil ;     url_session_manager_create_task_safely(^{         uploadTask = [self .session uploadTaskWithRequest:request fromData:bodyData];     });     [self  addDelegateForUploadTask:uploadTask progress:uploadProgressBlock completionHandler:completionHandler];     return  uploadTask; } 
其中 url_session_manager_create_task_safely 是解决iOS8之前的一个bug ,详情可以看 Issue 2093 
通过传入的NSURLRequest 生成NSURLSessionUploadTask 对象 
调用自定义方法 addDelegateForUploadTask...来为task添加回调事件 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - (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 ;     delegate.completionHandler = completionHandler;     dataTask.taskDescription = self .taskDescriptionForSessionTasks;     [self  setDelegate:delegate forTask:dataTask];     delegate.uploadProgressBlock = uploadProgressBlock;     delegate.downloadProgressBlock = downloadProgressBlock; } 
在这个方法中 AFURLSessionManagerTaskDelegate  类实现了 NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate代理。 
使用 setDelegate 来设置代理 
 
1 2 3 4 5 6 7 8 9 10 - (void )setDelegate:(AFURLSessionManagerTaskDelegate *)delegate             forTask:(NSURLSessionTask  *)task {     #检查参数          [self .lock lock];     self .mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;     [self  addNotificationObserverForTask:task];     [self .lock unlock]; } 
AFURLSessionManager 就是通过字典 mutableTaskDelegatesKeyedByTaskIdentifier  来存储并管理每一个 NSURLSessionTask,它以 taskIdentifier 为键存储 task。NSLock  来保证不同线程使用 mutableTaskDelegatesKeyedByTaskIdentifier 时,不会出现线程竞争 的问题。
实现 NSURLSessionDelegate 
AFURLSessionManager初始化的时候调用 initWithSessionConfiguration,将 NSURLSession 的代理设置为self
 
AFURLSessionManager实现了这些协议:
NSURLSessionDelegate 
NSURLSessionTaskDelegate 
NSURLSessionDataDelegate 
NSURLSessionDownloadDelegate 
 
所有的delegate 实现方法都提供对应的block接口,比如:
1 2 3 4 5 6 7 8 9 10 11 #pragma  mark - NSURLSessionDelegate - (void )URLSession:(NSURLSession  *)session didBecomeInvalidWithError:(NSError  *)error {     if  (self .sessionDidBecomeInvalid) {         self .sessionDidBecomeInvalid(session, error);     }     [[NSNotificationCenter  defaultCenter] postNotificationName:AFURLSessionDidInvalidateNotification object:session]; } 
对应的block接口是:
1 - (void )setSessionDidBecomeInvalidBlock:(nullable  void  (^)(NSURLSession  *session, NSError  *error))block; 
使用 AFURLSessionManagerTaskDelegate 管理进度 
上文的AFURLSessionManagerTaskDelegate实现了 NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate代理。
 
1 2 3 4 5 - (instancetype )initWithTask:(NSURLSessionTask  *)task {          1.  设置上传或者下载任务状态改变的是回调     2.  KVO } 
1.  设置上传或者下载任务状态改变的是回调
1 2 3 4 5 6 7 8 9 10 11 12 13 14 progress.totalUnitCount = NSURLSessionTransferSizeUnknown ;     progress.cancellable = YES ;     progress.cancellationHandler = ^{         [weakTask cancel];     };     progress.pausable = YES ;     progress.pausingHandler = ^{         [weakTask suspend];     };     if  ([progress respondsToSelector:@selector (setResumingHandler:)]) {         progress.resumingHandler = ^{             [weakTask resume];         };     } 
通过对应的NSProgress 状态改变时,调用 resume suspend等方法改变 task 的状态
2.  KVO
1 2 3 4 [progress addObserver:self                     forKeyPath:NSStringFromSelector (@selector (fractionCompleted))                       options:NSKeyValueObservingOptionNew                        context:NULL ]; 
1 2 3 4 5 6 7 8 9 10 11 12 - (void )observeValueForKeyPath:(NSString  *)keyPath ofObject:(id )object change:(NSDictionary <NSString  *,id > *)change context:(void  *)context {    if  ([object isEqual:self .downloadProgress]) {         if  (self .downloadProgressBlock) {             self .downloadProgressBlock(object);         }     }     else  if  ([object isEqual:self .uploadProgress]) {         if  (self .uploadProgressBlock) {             self .uploadProgressBlock(object);         }     } } 
对progress进行键值观察,对象的某些属性改变时更新 NSProgress 对象或使用 block 传递 NSProgress 对象 self.uploadProgressBlock(object)或者 self.downloadProgressBlock(object);。其中fractionCompleted表示 NSProgress的进度 。
代理方法 URLSession:task:didCompleteWithError: 
当task完成数据传输时会调用这个方法,接下来看一下在 AFURLSessionManagerTaskDelegate中的实现
 
1 2 3 4 5 6 7 8 9 10 11 12 13 - (void )URLSession:(__unused NSURLSession  *)session               task:(NSURLSessionTask  *)task didCompleteWithError:(NSError  *)error {     1.  取出数据。储存responseSerializer downloadFileURL          if (error){     	2.  有错误时调用completionHandler     }     else {     	3.  无错误时调用completionHandler     }  } 
1.  取出数据。储存responseSerializer downloadFileURL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 __strong  AFURLSessionManager *manager = self .manager;     __block id  responseObject = nil ;     __block NSMutableDictionary  *userInfo = [NSMutableDictionary  dictionary];     userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer;          NSData  *data = nil ;     if  (self .mutableData) {         data = [self .mutableData copy ];                  self .mutableData = nil ;     }     if  (self .downloadFileURL) {         userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self .downloadFileURL;     } else  if  (data) {         userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data;     } 
这部分代码从 mutableData 中取出了数据,设置了 userInfo。其中 self. mutableData 是从URLSession:dataTask:didReceiveData代理方法中获取的。userInfo 用来做通知时传送的数据
2. 3.调用completionHandler 
该代理方法中的error仅指本地端的错误,比如无法解析域名或者不能连上host等。
1 2 3 4 5 6 7 8 9 dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{             if  (self .completionHandler) {                 self .completionHandler(task.response, responseObject, error);             }             dispatch_async (dispatch_get_main_queue(), ^{                 [[NSNotificationCenter  defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];             });         }); 
如果当前 manager 持有 completionGroup 或者 completionQueue 就使用它们。否则会创建一个 dispatch_group_t 并在主线程中调用 completionHandler 并发送通知(在主线程中)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 NSError  *serializationError = nil ;            responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];             if  (self .downloadFileURL) {                 responseObject = self .downloadFileURL;             }             if  (responseObject) {                 userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject;             }             if  (serializationError) {                 userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError;             } 
如果没有error,先对数据进行序列化,然后同样调用 block 并发送通知。
_AFURLSessionTaskSwizzling 
因为 iOS7 和 iOS8 上对于 NSURLSessionTask 的实现不同,AFURLSessionTaskSwizzling 的就是修改 NSURLSessionTask 的 resume 和 suspend 方法
 
使用+load 替换方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 +(void )load{ 	if  (NSClassFromString (@"NSURLSessionTask" )) { 	        NSURLSessionConfiguration  *configuration = [NSURLSessionConfiguration  ephemeralSessionConfiguration];         NSURLSession  * session = [NSURLSession  sessionWithConfiguration:configuration]; #pragma  GCC diagnostic push #pragma  GCC diagnostic ignored "-Wnonnull"          NSURLSessionDataTask  *localDataTask = [session dataTaskWithURL:nil ]; #pragma  clang diagnostic pop         IMP originalAFResumeIMP = method_getImplementation(class_getInstanceMethod([self  class ], @selector (af_resume)));         Class currentClass = [localDataTask class ];                  while  (class_getInstanceMethod(currentClass, @selector (resume))) {             Class superClass = [currentClass superclass];             IMP classResumeIMP = method_getImplementation(class_getInstanceMethod(currentClass, @selector (resume)));             IMP superclassResumeIMP = method_getImplementation(class_getInstanceMethod(superClass, @selector (resume)));             if  (classResumeIMP != superclassResumeIMP &&                 originalAFResumeIMP != classResumeIMP) {                 [self  swizzleResumeAndSuspendMethodForClass:currentClass];             }             currentClass = [currentClass superclass];         }                  [localDataTask cancel];         [session finishTasksAndInvalidate];     } } 
首先用 NSClassFromString(@”NSURLSessionTask”) 判断当前部署的 iOS 版本是否含有类 NSURLSessionTask 
因为 iOS7 和 iOS8 上对于 NSURLSessionTask 的实现不同,所以会通过 - [NSURLSession dataTaskWithURL:] 方法返回一个 NSURLSessionTask 实例 
取得当前类 _AFURLSessionTaskSwizzling 中的实现 af_resume 
如果当前类 currentClass 有 resume 方法
 
使用 swizzleResumeAndSuspendMethodForClass: 调剂该类的 resume 和 suspend 方法 
currentClass = [currentClass superclass] 
 
使用 AFSecurityPolicy 保证请求的安全 AFSecurityPolicy  具体参考 AFNetworking3源码阅读-Security 
在代理方法 URLSession:didReceiveChallenge:completionHandler中调用
1 2 3 ... if  ([self .securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {...