Alamofire源码笔记

Alamofire

1. Alamofire结构

Alamofire全部实现共有17个文件组成,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
--------接口----------
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。
  • 其他 :另外,还有实现了两个协议CustomStringConvertibleCustomDebugStringConvertible。前者定义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转码。三种转码对应三个结构体:URLEncodingJSONEncodingPropertyListEncoding。他们都遵循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表单文档。

涉及到的知识比较深,需要补充一下。开个坑,以后填!

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)。
  • DataResponseDefaultDataResponse多两个属性: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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
--------协议---------
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: successfailure

  • 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,包含四个内部枚举:

1
2
3
4
* ParameterEncodingFailureReason // 参数编码错误
* MultipartEncodingFailureReason // 表单错误
* ResponseValidationFailureReason // 响应验证错误
* ResponseSerializationFailureReason // 数据序列化错误

除了四个内部枚举外,AFError本身还有一个,URL无效错误。

另外,还可以通过布尔值判断是否有错误。

AFError.swift涉及到内联枚举,枚举绑定值和提取判断等。

2.10 Validation.swift

Validation.swift主要用于服务器响应数据验证。

由三个扩展组成: Request扩展,DataRequest扩展,DownloadRequest扩展。第一个是基本验证,后两个是对不同的下载需求的验证。

接下来,看看具体实现了什么?

Request扩展

  • 两个属性,分别是acceptableStatusCodesacceptableContentTypes
  • 两个方法,分别是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 System

URL加载系统包括加载URL的类,以及一些重要的帮助类。主要的帮助类:协议支持,身份验证和凭据,Cookie存储,配置管理和缓存管理等。

小结

初步学习了Alamofire源码文件,并没有深入探究源码具体实现。后续内容稍后补充,先补补基础知识。🤣

参考