AFHTTPSessionManager

参考文章http://draveness.me/afnetworking2.html#NSURLSessionDelegate

这个里面基本上方法都是来先使用requestSerializer生成一个NSMutableRequest,再调用
- (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方法来完成请求,生成一个NSURLSessionDataTask,然后立马将这个dataTask来resume并返回.

  • 在调用requestSerializer生成NSMutableRequest的过程中,如果生成了serializationError, 都会,都会调用通过completionQueue来把错误传出来,如果没有completionQueue,就会通过mainQueue来传
  • 作者喜欢用?:, 会生成编译器警告,所以用clang diagnostic pushclang diagnostic pop来忽略编译器警告
1
2
3
4
5
6
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
failure(nil, serializationError);
});
#pragma clang diagnostic pop
  • 相关文档见http://nshipster.cn/clang-diagnostics/http://fuckingclangwarnings.com/

AFURLSessionManager

  • 初始化方法initinitWithSessionConfiguration:.
  • initWithSessionConfiguration初始化了sessionConfiguration和session,以及AFNetworkReachabilityManager

URLSessionDelegate

通过 NSURLSession来分析AFURLSessionManager
NSURLSession的结构

  • NSURLSessionDelegate 这里面实现session级别的三个代理方法,包括session结束,以及session中如果收到AuthenticationChallenge会调用这个方法。AFURLSessionManager对外面暴露了setSessionDidBecomeInvalidBlock:的方法和setSessionDidReceiveAuthenticationChallengeBlock方法
  • 如果在验证证书的时候,AFURLSessionManager没有实现sessionDidReceiveAuthenticationChallenge,那么就会调用securityPolicy来做证书验证。NSURLCredential会寻找相应的证书,返回正确的disposition给NSURLSessionDelegate里面的completionHandler

管理URLSessionTask

如何生成一个dataTask:

  • 调用了 NSURLSession的dataTaskWithRequest:生成了dataTask
  • 调用`- (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` 给这个dataTask生成了一个delegate
    

其中上面的add方法做了以下几个事情

  • 生成了一个AFURLSessionManagerTaskDelegate对象,并把上传,下载,进度,完成等管理的block全加入到了这个delegate当中。
  • 调用了`setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
    forTask:(NSURLSessionTask *)task`,
    

上面的setDelegate:forTask完成了几个事情

  • NSLock保证mutableTaskDelegatesKeyedByTaskIdentifier这个dictionary的修改是线程安全的
  • 将delegate放到了这个dictionary中,key为dataTask的taskIdentifier
  • 给NSURLSessionTask添加observer, 监听它的resume和suspend
  • 调用delegate的setupProgressForTask方法

上面setupProgressForTask完成了几个事情

  • 配置了delegate的uploadProgress, downloadProgress
  • 给nsurlsessiontask的进度添加了kvo,用来监听当前收到了多少字节
  • 给download和uploadprogress的进度添加了kvo用来监听是否完成

URLSessionTaskDelegate 管理进度相关

  • `- (void)URLSession:(NSURLSession *)session
    task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response  newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest *))completionHandler` 当发生302或者301的时候?请求发生redirection,这个时候代理会看下当前的SessionManager有没有处理回调的逻辑,并返回completion
    
  • URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler 这个跟上面session处理逻辑类似,不同的是上面是session碰到https,这边是task碰到https
  • - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task needNewBodyStream:(void (^)(NSInputStream *bodyStream))completionHandler
    这个暂时没有想到什么时候会需要这个情况,在dash里面文档是这样说的
1
2
3
    This delegate method is called under two circumstances:
To provide the initial request body stream if the task was created with uploadTask(withStreamedRequest:)
To provide a replacement request body stream if the task needs to resend a request that has a body stream because of an authentication challenge or other recoverable server error.

不过里面的处理比较简单,就是如果有设置block的花就调用block返回一个inputStream,否则就调用httprequest的HTTPBodyStream返回给completionHandler

  • - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend 一共发送了多少数据量,这里如果有设置block,就调用block,这样可以看到上传进度

  • - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error某一个请求已经完成。这个时候,会调用removeDelegateForTask:(NSURLSessionTask *)task:根据task找到本地dictionary的delegate。移除kvo,移除notification,然后从dictionary中删掉这个task

NSURLSessionDataDelegate

收到相应之后会调用这个delegate的方法,同时,有可能会转成一个下载任务,这里也会收到回调,同时,有可能下载任务又收到了一些数据,那么这个时候,会把data append到之前的data上 [self.mutableData appendData:data]; (这个是delegate做的).同时delegate还会询问是否需要cache。以及等所有的后台任务完成的时候会收到回调。http://www.cnblogs.com/polobymulberry/p/5140806.html

NSURLSessionDownloadDelegate

这个主要是下载时候的delegate, 包括是否完成,下载了多少,是否在下载多少百分比的时候resume

_AFURLSessionTaskSwizzling

主要就是为了swizzle resumesuspend 这两个NSURLSessionTask的方法。因为这个NSURLSessionTask没有delegate和block来知道状态,所以通过swizzle他们来在调用resume和suspend的时候发送两个notification

NSProgress使用

查看此文章,完成了基本的进度管理的功能,还可以派生子任务等
https://my.oschina.net/u/2340880/blog/679367