You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-(void)af_resume {NSAssert([self respondsToSelector:@selector(state)],@"Does not respond to state");
NSURLSessionTaskState state =[self state];[self af_resume];
-(void)af_suspend { NSAssert([self respondsToSelector:@selector(state)],@"Does not respond to state");
NSURLSessionTaskState state =[self state]; [self af_suspend];
AFNetworking 的核心 AFURLSessionManager(二)
https://draveness.me/
About 0 Minutes
Blog: Draveness
关注仓库,及时获得更新:iOS-Source-Code-Analyze
AFURLSessionManager
绝对可以称得上是 AFNetworking 的核心。我们会在这里着重介绍上面七个功能中的前五个,分析它是如何包装
NSURLSession
以及众多代理方法的。创建和管理
NSURLSession
在使用
AFURLSessionManager
时,第一件要做的事情一定是初始化:在初始化方法中,需要完成初始化一些自己持有的实例:
defaultSessionConfiguration
管理
NSURLSessionTask
接下来,在获得了
AFURLSessionManager
的实例之后,我们可以通过以下方法创建NSURLSessionDataTask
的实例:这里省略了一些返回
NSURLSessionTask
的方法,因为这些接口的形式都是差不多的。我们将以
- [AFURLSessionManager dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:]
方法的实现为例,分析它是如何实例化并返回一个NSURLSessionTask
的实例的:- [NSURLSession dataTaskWithRequest:]
方法传入NSURLRequest
- [AFURLSessionManager addDelegateForDataTask:uploadProgress:downloadProgress:completionHandler:]
方法返回一个AFURLSessionManagerTaskDelegate
对象completionHandler
uploadProgressBlock
和downloadProgressBlock
传入该对象并在相应事件发生时进行回调在这个方法中同时调用了另一个方法
- [AFURLSessionManager setDelegate:forTask:]
来设置代理:正如上面所提到的,
AFNRUSessionManager
就是通过字典mutableTaskDelegatesKeyedByTaskIdentifier
来存储并管理每一个NSURLSessionTask
,它以taskIdentifier
为键存储 task。该方法使用
NSLock
来保证不同线程使用mutableTaskDelegatesKeyedByTaskIdentifier
时,不会出现线程竞争的问题。同时调用 - setupProgressForTask:,我们会在下面具体介绍这个方法。
实现
NSURLSessionDelegate
等协议中的代理方法在
AFURLSessionManager
的头文件中可以看到,它遵循了多个协议,其中包括:NSURLSessionDelegate
NSURLSessionTaskDelegate
NSURLSessionDataDelegate
NSURLSessionDownloadDelegate
它在初始化方法
- [AFURLSessionManager initWithSessionConfiguration:]
将NSURLSession
的代理指向self
,然后实现这些方法,提供更简洁的 block 的接口:它为所有的代理协议都提供了对应的 block 接口,方法实现的思路都是相似的,我们以
- [AFNRLSessionManager setSessionDidBecomeInvalidBlock:]
为例。首先调用 setter 方法,将 block 存入
sessionDidBecomeInvalid
属性中:当代理方法调用时,如果存在对应的 block,会执行对应的 block:
其他相似的接口实现也都差不多,这里直接跳过了。
使用
AFURLSessionManagerTaskDelegate
管理进度在上面我们提到过
AFURLSessionManagerTaskDelegate
类,它主要为 task 提供进度管理功能,并在 task 结束时回调, 也就是调用在- [AFURLSessionManager dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:]
等方法中传入的completionHandler
。我们首先分析一下
AFURLSessionManagerTaskDelegate
是如何对进度进行跟踪的:该方法的实现有两个部分,一部分是对代理持有的两个属性
uploadProgress
和downloadProgress
设置回调这里只有对
uploadProgress
设置回调的代码,设置downloadProgress
与这里完全相同第二部分是对 task 和
NSProgress
属性进行键值观测:在
observeValueForKeypath:ofObject:change:context:
方法中改变进度,并调用 block对象的某些属性改变时更新
NSProgress
对象或使用 block 传递NSProgress
对象self.uploadProgressBlock(object)
。代理方法
URLSession:task:didCompleteWithError:
在每一个
NSURLSessionTask
结束时,都会在代理方法URLSession:task:didCompleteWithError:
中:completionHander
blockAFNetworkingTaskDidCompleteNotification
通知这是整个代理方法的骨架,先看一下最简单的第一部分代码:
这部分代码从
mutableData
中取出了数据,设置了userInfo
。如果当前
manager
持有completionGroup
或者completionQueue
就使用它们。否则会创建一个dispatch_group_t
并在主线程中调用completionHandler
并发送通知(在主线程中)。如果在执行当前 task 时没有遇到错误,那么先对数据进行序列化,然后同样调用 block 并发送通知。
代理方法
URLSession:dataTask:didReceiveData:
和- URLSession:downloadTask:didFinishDownloadingToURL:
这两个代理方法分别会在收到数据或者完成下载对应文件时调用,作用分别是为
mutableData
追加数据和处理下载的文件:使用
_AFURLSessionTaskSwizzling
调剂方法_AFURLSessionTaskSwizzling
的唯一功能就是修改NSURLSessionTask
的resume
和suspend
方法,使用下面的方法替换原有的实现这样做的目的是为了在方法
resume
或者suspend
被调用时发出通知。具体方法调剂的过程是在
+ load
方法中进行的NSClassFromString(@"NSURLSessionTask")
判断当前部署的 iOS 版本是否含有类NSURLSessionTask
NSURLSessionTask
的实现不同,所以会通过- [NSURLSession dataTaskWithURL:]
方法返回一个NSURLSessionTask
实例_AFURLSessionTaskSwizzling
中的实现af_resume
currentClass
有resume
方法swizzleResumeAndSuspendMethodForClass:
调剂该类的resume
和suspend
方法currentClass = [currentClass superclass]
引入
AFSecurityPolicy
保证请求的安全AFSecurityPolicy
是AFNetworking
用来保证 HTTP 请求安全的类,它被AFURLSessionManager
持有,如果你在AFURLSessionManager
的实现文件中搜索 self.securityPolicy,你只会得到三条结果:self.securityPolicy = [AFSecurityPolicy defaultPolicy]
在 API 调用上,后两者都调用了
- [AFSecurityPolicy evaluateServerTrust:forDomain:]
方法来判断当前服务器是否被信任,我们会在接下来的文章中具体介绍这个方法的实现的作用。如果没有传入
taskDidReceiveAuthenticationChallenge
block,只有在上述方法返回YES
时,才会获得认证凭证credential
。引入
AFNetworkReachabilityManager
监控网络状态与
AFSecurityPolicy
相同,AFURLSessionManager
对网络状态的监控是由AFNetworkReachabilityManager
来负责的,它仅仅是持有一个AFNetworkReachabilityManager
的对象。小结
AFURLSessionManager
是对NSURLSession
的封装- [AFURLSessionManager dataTaskWithRequest:completionHandler:]
等接口创建NSURLSessionDataTask
的实例mutableTaskDelegatesKeyedByTaskIdentifier
管理这些 data task 实例AFURLSessionManagerTaskDelegate
来对传入的uploadProgressBlock
downloadProgressBlock
completionHandler
在合适的时间进行调用关于其他 AFNetworking 源代码分析的其他文章:
关注仓库,及时获得更新:iOS-Source-Code-Analyze
Blog: Draveness
关于图片和转载
本作品采用知识共享署名 4.0 国际许可协议进行许可。 转载时请注明原文链接,图片在使用时请保留图片中的全部内容,可适当缩放并在引用处附上图片所在的文章链接,图片使用 Sketch 进行绘制。
微信公众号
关于评论和留言
如果对本文 AFNetworking 的核心 AFURLSessionManager(二) 的内容有疑问,请在下面的评论系统中留言,谢谢。Comp
via 面向信仰编程 https://draveness.me
April 30, 2019 at 11:19AM
The text was updated successfully, but these errors were encountered: