说说你会用但是不了解的好朋友
刚开始被问到 :来妹妹~你给我讲一下AF
顿时一脸懵逼 有时候你懂得一个东西是做什么的 但是又不会去想为什么这么做 真的很尴尬呐
来看看官方介绍:
AFNetworking is a delightful networking library for iOS and Mac OS X. It’s built on top of theFoundation URL Loading System, extending the powerful high-level networking abstractions built into Cocoa. It has a modular architecture with well-designed, feature-rich APIs that are a joy to use.
Perhaps the most important feature of all, however, is the amazing community of developers who use and contribute to AFNetworking every day. AFNetworking powers some of the most popular and critically-acclaimed apps on the iPhone, iPad, and Mac.
Choose AFNetworking for your next project, or migrate over your existing projects—you’ll be happy you did!
简单翻译一下:AFNetworking是一个适用于iOS和Mac OS X两个平台的网络库 是基于Foundation URL Loading System上的一套封装 并且提供了丰富优美的API接口给使用者使用
一听就很了不起
选择AFNetworking 版本3.0 逐字逐句的去了解 由于本人不是很喜欢逗号分号这类的 所以全篇无逗号分号 能看就看
没办法Swift惯的~摊手
那就从源码开始说起
![](https://img.haomeiwen.com/i3494527/da0c04f49ede49e9.png)
用AF3.0的举
拿AFURLSessionManager开刀
![](https://img.haomeiwen.com/i3494527/dd637938d4c9e672.png)
以上的属性 可以分别拿到的是:总的任务集合、数据任务集合、上传任务集合和下载任务集合
![](https://img.haomeiwen.com/i3494527/89b319464e8a5aff.png)
上面的属性非常重要 特意把注释一起放上来 注释里写到:iOS7中存在一个bug 在创建后台上传任务时 有时候会返回nil 所以为了解决这个问题 AFNetworking遵照里苹果的建议 在创建失败的时候 会重新尝试创建 次数默认为3次 所以你的应用如果有场景会在后台上传的情况的话 记得将该值设为YES 避免出现上传失败的问题
*AFNetworking是对NSURLConnection和NSURLSession的各自一层包装
—AFNetworking的内部中的RunLoop
AFNetworking内部开辟一条专门用来访问网络请求的线程
在这个开线程的方法中 他把方法和dispatch _once 都用static修饰
以保证这个方法的安全性以及开笔一块内存空间 病区保证线程不死
在这个方法中他会调用另一个网络请求的方法
在Xcode 7之后 NSURLConnection的API已经正式被苹果遗弃 虽然还可以使用 但是新功能不会再被添加
意味着什么 意味着已经放弃了对其维护 那么就好好告别吧
所以之前熟悉的好朋友:
AFURLConnectionOperation
AFHTTPRequestOperation
AFHTTPRequestOperationManager
这些类已经从3.0中废弃
AFURLSessionManager继承自NSObject 服从
NSURLSessionDelegate
NSURLSessionTaskDelegate
NSURLSessionDataDelegate
NSURLSeesionDownloadDelegate
NSSecureCoding
NSCopying
以上协议
是用来NSURLSession的封装单元
AFURLSessionManager中包含三个部分:
AFURLSessionManagerTaskDelegate:用来管理网络请求的信息 并且处理请求完成的回调
_AFURLSessionTaskSwizzling:用来完成resume与af_resume的swizzling的类
AFURLSessionManager:主体控制网络请求的相关功能在AFURLSessionManager中 创建一个NSOperationQueue 最大operation数为1
规定请求delegate的OperationQueue是唯一的 在这个类中开辟了唯一的一个串行队列url_session_manager_creation_queue来调用NSURLSession的请求方法 唯一的一个并行队列url_session_manager_processing_queue来进行编程 使用唯一的一个group url_session_manager_completion_group来管理完成线程
为了保证线程安全 所以得到的单例都是使用dispatch_once生成
![](https://img.haomeiwen.com/i3494527/7e8bc0c2ae54e72b.png)
并且通过KVO监控resume情况
![](https://img.haomeiwen.com/i3494527/18021b3b64a80d59.png)
调用网络请求的方法中 会创建一个NSURLSessionDataTask对象 用来返回给用户 在之前单例创建的线程中 url_session_manager_creation_queue调用init中创建的session属性来执行请求中的方法
![](https://img.haomeiwen.com/i3494527/ac681f74e3414f91.png)
由-(void)addDelegateForDataTask可以看出来在框架中用于管理请求信息与数据的回调的事AFURLSessionManagerTaskDelegate
![](https://img.haomeiwen.com/i3494527/acfff48268ac3e37.png)
AFURLSessionManagerTaskDelegate和NSURLSessionTask的关系是由AFURLSessionManager管理的
addDelegateForDataTask方法中除了创建AFURLSessionManagerTaskDelegate类鱼配置其属性以外 如果是上传 会配置content-length以及delegate.progress的相关block属性
如果是下载 则会配置download的block属性
![](https://img.haomeiwen.com/i3494527/7921cfc252682d48.png)
之后的一个方法是setDelegate:forTask:它将AFURLSessionManagerTaskDelegate与NSURLSessionDataTask进行了绑定 方便之后对于请求数据的查找与回调
mutableTaskDelegatesKeyedByTaskIdentifier是将task的taskIdentifier与delegate绑定的重要属性
![](https://img.haomeiwen.com/i3494527/da8e348c7605b3f9.png)
我们想要得到包括进程等等属性都在delegate里面可以得到
在resume时需要外界能接到一个didResume的消息 所以需要调用taskDidResume方法
![](https://img.haomeiwen.com/i3494527/d968971b75d6a914.png)
终于得到了AFNetworkingTaskDidResumeNotification 有了它久方便多了 AFNetworkingTaskDidSuspendNotification也是同理
在这里其实还有一个很重要的知识点 :
AFNetworking对NSURLSessionTask中的state进行了KVO处理
但是在iOS8上会导致莫名的crash 可能是由于iOS7与iOS8上的NSURLSessionTask是不同的
还好可以用swizzling解决这个问题 在源码中我们可以看到如果想要得到AFNetworkingTaskDidResumeNotification通知 就要执行
-(void)taskDidResume:(NSNotification *)notification 方法
而这个方法是需要通过监听AFNSURLSessionTaskDidResumeNotification 来通知执行的
所以我们需要对resume方法进行修改 在resume方法中添加此通知 于是就通过swizzling
在+(void)load 中将af_resume与resume 方法的imp进行交换
af_resume方法实现
![](https://img.haomeiwen.com/i3494527/d0eb0c7f4c8bde17.png)
简单来说就是将af_resume的函数指针与resume的函数指针进行调换 在调用resume方法时其实就是调用的就是af_resume方法 调用af_resume时则相反
在网络请求的过程中 AFURLSessionManager在执行相关的NSURLSessionDelegate方法时 回调用这个请求相对应的AFURLSessionManagerTaskDelegate类中的对应的NSURLSessionDelegate方法 在AFURLSessionDelegate方法 在AFURLSessionManagerTaskDelegate中完成请求的信息和数据回调
AFURLSessionManager中的NSURLSessionDelegate回调
![](https://img.haomeiwen.com/i3494527/fbb4d62c9c4c0997.png)
在AFURLSessionManagerTaskDelegate中的complete方法中则创建一个userInfo字典 存储网络请求的相关信息 然后通过消息中心post AFNetworkingTaskDidCompleteNotification 消息将userInfo传出
其中 还在completionGroup中调用主线程通过执行completionHandler将请求数据传出
到此为止终于完成了一次完整的网络请求
AFURLSessionManagerTaskDelegate中的NSURLSessionDelegate回调
![](https://img.haomeiwen.com/i3494527/b055dadc8b52ab7c.png)
![](https://img.haomeiwen.com/i3494527/5e56bd2b9237d5f4.png)