AFN的底层原理几乎是 iOS 面试必问的一个问题. 很多小伙伴纠结于 只要会用不就好了吗? 为什么面试造火车,进去拧螺丝! 其实业务代码对往高级的开发人员来说只是一个最基本的能力. 要想代码写的好, 维护性好, 耦合性低. 学习优秀框架的原理是必须的.
总得概括: AFN 框架的底层是基于 NSURLSession 的二次封装. 当然扩展了自己很多的功能
本篇文章将会按照我自己的理解进行讲解. 如果有什么错误的地方,请各位大神指正, 交流
那么既然是基于 NSURLSession 的封装, 那我们我们首先来熟悉一下
NSURLSession的使用!
一:创建 url
guard let url = URL(string: "http://v.juhe.cn/toutiao/index?type=&page=&page_size=&is_filter=&key=0b35bec413d59aab9f7a5abcbccb21ab") else { return }
二:创建NSMutableURLRequest
//第一个参数就是 url 第二个是缓存策略 第三个是超时时间
/****NSURLRequestCachePolicy枚举值:**
**NSURLRequestUseProtocolCachePolicy = 0:**默认的缓存策略, 如果缓存不存在,直接从服务端获取。如果缓存存在,会根据response中的Cache-Control字段判断下一步操作,如: Cache-Control字段为must-revalidata, 则询问服务端该数据是否有更新,无更新的话直接返回给用户缓存数据,若已更新,则请求服务端。
**NSURLRequestReloadIgnoringLocalCacheData = 1:**数据需要从原始地址加载。不使用现有缓存。
**NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4:**不仅忽略本地缓存,同时也忽略代理服务器或其他中间介质目前已有的、协议允许的缓存。
**NSURLRequestReturnCacheDataElseLoad = 2:**无论缓存是否过期,先使用本地缓存数据。如果缓存中没有请求所对应的数据,那么从原始地址加载数据。
**NSURLRequestReturnCacheDataDontLoad = 3:**无论缓存是否过期,先使用本地缓存数据。如果在缓存中没有已存数据来响应URL加载请求的话,不去尝试从源段加载数据,此时认为加载请求失败,(即:“离线”模式)。
**NSURLRequestReloadRevalidatingCacheData = 5:**从原始地址确认缓存数据的合法性后,缓存数据就可以使用,否则从原始地址加载(在使用前去服务器验证)。**/
let request = NSMutableURLRequest(url: url, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringCacheData, timeoutInterval: 15)
//设置请求方式
request.httpMethod = "GET"
三: 创建 URLSessionConfiguration
这一步就是创建默认的会话配置, 也就是相关的网络请求配置,下面是相关的属性解释.
/**1、class var `default`: URLSessionConfiguration // 默认的URL会话配置对象,其存储方式是基于硬盘的持久化存储方式,会保存用户的证书到钥匙串中
2、class var ephemeral: URLSessionConfiguration // 与第一个类似,不同之处在于存储的位置不同,此方式存储的位置是内存中
3、class func background(withIdentifier: String) -> URLSessionConfiguration
创建一个可以在后台甚至APP已经关闭的时候仍然在传输数据的会话。注意,后台Session一定要在创建的时候赋予一个唯一的identifier,这样在APP下次运行的时候,能够根据identifier来进行相关的区分。
如果用户关闭了APP,IOS 系统会关闭所有的background Session。而且,被用户强制关闭了以后,IOS系统不会主动唤醒APP,只有用户下次启动了APP,数据传输才会继续。
1、var identifier: String? // 配置后台会话的唯一标识符
2、var httpAdditionalHeaders: [AnyHashable : Any]? // 请求头
3、var networkServiceType: NSURLRequest.NetworkServiceType // 网络服务类型
4、var allowsCellularAccess: Bool // 会话是否允许蜂窝数据
5、var timeoutIntervalForRequest: TimeInterval // 进行请求连接的超时时间
6、var timeoutIntervalForResource: TimeInterval // 允许请求的请求最长时间
7、var sharedContainerIdentifier: String? // 后台URL会话中的共享标识符
8、var waitsForConnectivity: Bool // 等待连接是否立刻改变成可用或者不可用**/
//这里采用默认的
let config = URLSessionConfiguration.default
四: 创建会话URLSession
//第一个参数是会话配置 第二个是代理 第三个是当前代理的线程
let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
五: 发送请求
session.dataTask(with: request as URLRequest) { data, reaponse, error in
let str = String(data: data!, encoding: .utf8)
print("返回的数据是----\(str)")
}.resume()
结果
代码预览
guard let url = URL(string: "http://v.juhe.cn/toutiao/index?type=&page=&page_size=&is_filter=&key=0b35bec413d59aab9f7a5abcbccb21ab") else { return }
let request = NSMutableURLRequest(url: url, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringCacheData, timeoutInterval: 15)
request.httpMethod = "GET"
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
session.dataTask(with: request as URLRequest) { data, reaponse, error in
let str = String(data: data!, encoding: .utf8)
print("返回的数据是----\(str)")
}.resume()