AFNetworking 源码解析

时间:2021-04-08 18:34:22

3.0 之后,就取消了NSOperation的控制。

因为根据Apple Developer Document的文档 https://developer.apple.com/documentation/foundation/nsurlsession/1411597-sessionwithconfiguration , 初始化NSURLSession的queue有以下的限制

queue

An operation queue for scheduling the delegate calls and completion handlers. The queue should be a serial queue, in order to ensure the correct ordering of callbacks. If nil, the session creates a serial operation queue for performing all delegate method calls and completion handler calls.

所以AFnetworking的里面的NSOperationQueue设置如下,达到为串行的效果,注意串行不保证为FIFO。

    self.operationQueue = [[NSOperationQueue alloc] init];
self.operationQueue.maxConcurrentOperationCount = ;

使用NSLock 来保护一个保存taskidentifier的NSMutableDicitionary.

使用 semphore 来返回正在执行的任务列表 ,利用URLSession里面的接口,形成了一个串行执行的顺序,https://developer.apple.com/documentation/foundation/nsurlsession/1411578-gettaskswithcompletionhandler

使用_cmd 巧妙的标示不同的函数入口,cmd在Objective-C的方法中表示当前方法的selector,正如同self表示当前方法调用的对象实例。

如果回包里面header 没有content-length表述数据有多大,那么就不能察觉网路请求的进度,一些接口与属性就失效。

使用+load swizzle 实现监听系统接口某些函数执行的功能,比如URLSession的resume, suspend, 但是由于iOS8,iOS7之间有些继承关系不一样,一些父类会执行名字相同的函数,所以用一个for循环一直替换函数实现,一直到父类没有对应的不同实现的函数为止。这个功能是经过多次艰辛的调试迭代出来的,请看过程https://github.com/AFNetworking/AFNetworking/pull/2702

使用Runloop,

SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);

[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes

选择使用了

根据2015的WWDC Session711,我们知道iOS9+NSURLSession开始正式支持HTTP /2,更加人性化API,更加快。

于是在HTTP 1.1中,出现了Connection: keep-alive。 这个优化选项,可以使得客户端和服务器端复用一个TCP连接,从而减小每次的网络请求时间底层是否重新创建新的tcp连接并不由上层控制,而是urlsession来决定。最大数设定为1时,由于并发数过小,因此只能选择唯一的连接通道。多设置几个并发数,是否复用,取决于当前同时的请求数,以及服务器给你的协商。

而如果不使用共享,则会每次都开启多个tcp管道,并且最终连接数量不可控 

NSURLRequestUseProtocolCachePolicy 这个是默认的缓存策略,缓存不存在,就请求服务器,缓存存在,会根据response中的Cache-Control字段判断下一步操作,如: Cache-Control字段为must-revalidata, 则询问服务端该数据是否有更新,无更新的话直接返回给用户缓存数据,若已更新,则请求服务端。

还有下载进度这个,必须获取回包的header,看里面是否content-length,这样URLSession才能计算出总的长度,才知道百分比。

如何防止循环引用?http://nelson.logdown.com/posts/2017/03/28/retain-cycle-in-afnetworking

當我們呼叫 invalidateSessionCancelingTasks: 函式,它會去呼叫 NSURLSession 的 invalidateAndCancel 或 finishTasksAndInvalidate。根據蘋果文件,呼叫這兩個函式之後,NSURLSession 才會斷開它與 delegate 的關聯。至此,才打破 retain cycle。

解法

有兩個解法,第一個就是如上所述,記得最後要呼叫 invalidateSessionCancelingTasks: 來結束任務。第二個就是把 AFHTTPSessionManager 寫成 singleton,這樣有 retain cycle 也無所謂了。

    self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];