Alamofire源码分析笔记
1. Alamofire结构
Alamofire全部实现共有17个文件组成,如下:
--------接口----------
Alamofire.swift // api 声明
--------请求----------
Request.swift // 请求类,用于构建请求
ParameterEncoding.swift // 参数编码
MultipartFormData.swift // 自定义表单类
ServerTrustPolicy.swift // 服务器验证
--------响应-----------
Response.swift // 相应类,用于构建响应
ResponseSerialization.swift // 响应数据序列化
Validation.swift // 响应数据验证
Result.swift // 请求结果表示
AFError.swift // 错误类型
--------底层-----------
SessionManager.swift // 请求session的管理类,底层使用NSURLSession实现
SessionDelegate.swift // 请求Session的代理对象,主要实现NSURLSession的代理方法以及回调闭包
TaskDelegate.swift // 请求Task任务的代理对象,主要实现NSURLDataTask的代理方法
DispatchQueue+Alamofire.swift //GCD扩展,定义多个不同功能的队列
---------其他-----------
NetworkReachabilityManager.swift // 网络状态监听类
Notifications.swift // 定义通知
Timeline.swift //描述请求有关的时间 结构体
Alamofire有五模块组成,即接口、请求、响应、底层和其他。分析各模块的实现,功能和联系就可以理解Alamofire。
2. Alamofire源码分析
2.1 Alamofire.swift文件
查看源码可以发现分为两部分:
- 一部分主要是协议的定义和相关URL转换,如String,URL,URLComponent转URL,并且抛出异常。
- 另一部分,定义公开的接口,分别是数据请求(Data Request)、下载请求(Download Request)、上传请求(Upload Request)和流传输请求(Stream Request)。
主要分析第二部分:
-
@discardableResult
作用忽略返回值警告。 - 所有方法的调用都需要使用
SessionManager.default.xxx
。这说明SessionManager
是所有请求的入口和管理中心。 - 每个请求都会返回XXXRequest对象,关于XXXRequest对象,在后面会分析。
2.2 Request.swift文件
上面提到每个请求的返回值都是XXXRequest类型。
在Request.swift
文件中定义了五个类,分别是Request、DataRequest、DownloadRequest、UploadRequest和StreamRequest。其中Request为基类。
2.2.1 Request类
基类Request,定义了与HTTP请求相关的属性和方法。
- 属性 :代理delegate(TaskDelegate)和Foundation框架中与URL请求相关的四个属性,分别是task(URLSessionTask)、session(URLSession)、request(URLRequest)和response(HTTPURLResponse)。除此之外,还有重试请求次数retryCount、请求开始时间startTime和结束时间endTime,以及验证闭包validations。
-
方法 :基类Request提供初始化方法
init(session: URLSession, requestTask: RequestTask, error: Error? = nil)
默认访问权限internal
,一般是SessionManager
调用创建request
,外部不需要创建。另外还有三个服务器验证和三个请求状态的方法resume()
、suspend()
和cancel()
,其作用是调用成员属性task和发送对应的通知,如Notification.Name.Task.DidResume。 -
其他 :另外,还有实现了两个协议
CustomStringConvertible
和CustomDebugStringConvertible
。前者定义description
包含了http方法、url和响应状态码,后者是比较具体的debug。
2.2.2 DataRequest类
子类DataRequest,管理底层的URLSessionDataTask
。主要用于简单的HTTP请求,GET和POST等。
- 属性 :其中包含三个属性,request(URLRequest)、progress和dataDelegate,其中dataDelegate必须向下转换(as!)为DataTaskDelegate类型。
-
方法 : 另外,还有两个方法
open func stream(closure: ((Data) -> Void)? = nil) -> Self
和open func downloadProgress(queue: DispatchQueue = DispatchQueue.main, closure: @escaping ProgressHandler) -> Self
分别用来设置流闭包和下载进度闭包操作。
2.2.3 DownloadRequest类
子类DownloadRequest,管理底层URLSessionDownloadTask
。实现下载请求。包含三个部分辅助类型、属性、和方法。
- 辅助类型 : DownloadOption(OptionSet)用于移动下载文件从临时URL到目标URL。闭包类型DownloadFileDestination决定下载请求完成后临时文件写入的位置。两个参数:临时文件URL和URL Response。两个返回值参数:目标URL和定义如何移动(DownloadOptions)。枚举类型Downloadable。
- 属性 :request(URLRequest)、resumeData(暂停或者失败,用于重新开启)、progress(下载进度)和 downloadDelegate(下载代理)。
-
方法 :
open override func cancel()
和open func downloadProgress(queue: DispatchQueue = DispatchQueue.main, closure: @escaping ProgressHandler) -> Self
。前者用于取消下载,后者设置下载过程的闭包和执行队列。
2.2.4 UploadRequest类
上传请求,DataRequest的子类。三个属性,一个方法。
- 属性 : request(URLRequest)、uploadPregress(上传进度)和uploadDelegate(上传代理)
-
方法 :
open func uploadProgress(queue: DispatchQueue = DispatchQueue.main, closure: @escaping ProgressHandler) -> Self
后者设置上传过程的闭包和执行队列。
2.2.5 StreamRequest类
流请求,没有定义属性和方法,是Request的子类。
2.2.6 对比
对比四个子类,他们对应普通请求、下载请求、上传请求和流传输请求。我们注意到一些相似之处,
- 他们都有遵循TaskConvertble协议的枚举类型。 其中唯一的方法:
task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask
,用于创建对应的task,并对urlRequest做适配。 - Request的delegate/taskDelegate与各个子类中的XXXTaskDelegate的作用是相同的,就是用于创建
TaskDelegate.swift
文件中的各种代理实例,用来处理URLSessionDelegate
的请求。稍后我们在分析TaskDelegate.swift
。
2.3 ParameterEncoding.swift文件
由名字可以理解该文件负责对请求参数进行转码,如:URL转码、JSON转码和PropertyList转码。三种转码对应三个结构体:URLEncoding
,JSONEncoding
和PropertyListEncoding
。他们都遵循ParameterEncoding
协议。协议只有一个方法:func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest
, 把参数转成目标格式,另外还设置HTTP头部的信息。例如Content-Type:application/json
。
2.4 MultipartFormData.swift文件
构建用于在HTTP或HTTPS主体中上传的multipart/form-data。 目前有两种编码多部分表单数据的方式。 第一种方法是直接在内存中编码数据。 这是非常有效的,但如果数据集太大,可能会导致内存问题。 第二种方式是设计用于较大的数据集,并将所有数据写入磁盘上的单个文件,并具有所有正确的边界分割。 第二种方法必须用于较大的数据集,如视频内容,否则,当您尝试对数据集进行编码时,应用程序可能会耗尽内存。
有关multipart/form-data的更多信息,请参考RFC-2388和RFC-2045规范以及w3表单文档。
- https://www.ietf.org/rfc/rfc2388.
- https://www.ietf.org/rfc/rfc2045.
- https://www.w3.org/TR/html401/interact/forms.html#h-17.13
涉及到的知识比较深,需要补充一下。开个坑,以后填!
2.5 ServerTrustPolicy.swift文件
服务器验证。开个坑,以后填!
2.6 Response.swift文件
Response.swift中,有四个结构体,分别是DefaultDataResponse/DataResponse, DefaultDownloadResponse/DownloadResponse。 其中Default是未经格式化的。前两个用于普通数据请求和上传,后俩个用于下载。主要功能是存储响应相关值。
2.6.1 DefaultDataResponse/DataResponse结构体
- s属性 :有五个属性request(URLRequest)、response(HTTPURLResponse)、data(返回的数据)、error(请求错误信息)和timeline(请求时间线,对应Timeline.swift)。
-
DataResponse
比DefaultDataResponse
多两个属性:value(result.value)和result(序列化数据)。其他属性相同。
2.6.2 DefaultDownloadResponse/DownloadResponse结构体
- 属性 : 有七个属性,request(URLRequest)、response(HTTPURLResponse)、temporaryURL(临时地址)、destinationURL(最终地址/重定向地址)、resumeData(下载取消时的contentOffset)、error(请求错误信息)和timeline(请求时间线,对应Timeline.swift)
-
DownloadResponse
同样多了两个属性。
2.6.3 对比
无论是DataResponse还是DownloadResponse都有两个方法:public func map<T>(_ transform: (Value) -> T) -> XXXResponse<T>
和public func flatMap<T>(_ transform: (Value) throws -> T) -> XXXResponse<T>
用于数据转化,区别在于后者会抛出异常。无论是服务器原始数据,还是序列化后的数据,都会被存放在result枚举的case绑定的元组中,success为泛型,failure为Error。具体内容后面在Result.swift中讲解。
2.7 ResponseSerialization.swift文件
查看源码,文件由两个协议、两个结构体和多个extension组成。
--------协议---------
1. DataResponseSerializerProtocol
2. DownloadResponseSerializerProtocol
--------结构体--------
1. DataResponseSerializer<Value>
2. DownloadResponseSerializer<Value>
--------Request扩展------
0. Timeline
1. Default
2. Data
3. String
4. JSON
5. Property List
- Request扩展中2-5都依赖于扩展1的方法,底层调用构造response,几种序列化过程基本相同。
具体内容,后期补充。
2.8 Result.swift
一个枚举类型Result,有两个case: success
和failure
。
- success: 绑定指定的泛型实例
- fialure: 绑定Error
两个主要的方法
public func map<T>(_ transform: (Value) -> T) -> Result<T>
public func flatMap<T>(_ transform: (Value) throws -> T) -> Result<T>
两者区别,前者不会抛出一样。
2.9 AFError.swift
枚举类型AFError,包含四个内部枚举:
* ParameterEncodingFailureReason // 参数编码错误
* MultipartEncodingFailureReason // 表单错误
* ResponseValidationFailureReason // 响应验证错误
* ResponseSerializationFailureReason // 数据序列化错误
除了四个内部枚举外,AFError本身还有一个,URL无效错误。
另外,还可以通过布尔值判断是否有错误。
AFError.swift涉及到内联枚举,枚举绑定值和提取判断等。
2.10 Validation.swift
Validation.swift主要用于服务器响应数据验证。
由三个扩展组成: Request扩展,DataRequest扩展,DownloadRequest扩展。第一个是基本验证,后两个是对不同的下载需求的验证。
接下来,看看具体实现了什么?
Request扩展
- 两个属性,分别是
acceptableStatusCodes
和acceptableContentTypes
- 两个方法,分别是
fileprivate func validate<S: Sequence>( statusCode acceptableStatusCodes: S, response: HTTPURLResponse) -> ValidationResult where S.Iterator.Element == Int
和
fileprivate func validate<S: Sequence>( contentType acceptableContentTypes: S, response: HTTPURLResponse, data: Data?) -> ValidationResult where S.Iterator.Element == String
这两个属性和方法分别用于验证StatusCode和ContentType。
DataRequest扩展
四个方法:
-
validate(_:)
: 基础方法,接收Validation类型闭包,构建validationExecution,添加到验证队列中。 -
validate(statusCode:)
: 验证StatusCode -
validate(contentType:)
:验证ContentType -
validate()
:同时验证StatusCode和ContentType
2.11 SessionManager.swift/SessionDelegate.swift/TaskDelegate.swift
- SessionManager负责Session的创建和管理,请求的创建和发起
- SessionDelegate/TaskDelegate负责处理请求的响应
SessionManager共有10个属性,主要的几个:
- default : 一个单例,对外的接口都调用这个实例。
- defaultHTTPHeader: 请求头,定义了默认HTTP头部信息
- backgroundCompletionHandler: APP进入后台时完成的闭包,需要手动设置和调用。
- queue: 每个Session私有的任务队列
接下来是初始化方法,SessionManager初始化过程:
- 1.调用者通过func request(_ urlRequest: URLRequestConvertible) -> DataRequest方法调用
- 2.SessionManager通过传入urlRequest创建适配的urlRequest(Request适配器)
- 3.调用Request.Requestable.task(:::)创建对应SessionTask
- 4.创建对应的XXXRequest实例
- 5.将XXXRequest设置到Delegate[task]下标
- 6.开始任务
另外,还有错误处理,重试等内容。
补充
1. URL Loading System架构
URL Loading SystemURL加载系统包括加载URL的类,以及一些重要的帮助类。主要的帮助类:协议支持,身份验证和凭据,Cookie存储,配置管理和缓存管理等。
小结
初步学习了Alamofire源码文件,并没有深入探究源码具体实现。后续内容稍后补充,先补补基础知识。🤣