美文网首页iOS 进阶文集
Alamofire源码分析笔记

Alamofire源码分析笔记

作者: 繁华落尽丶lee | 来源:发表于2017-10-17 08:31 被阅读44次
    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。
    • 其他 :另外,还有实现了两个协议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) -> Selfopen 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. 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,包含四个内部枚举:

    * 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源码文件,并没有深入探究源码具体实现。后续内容稍后补充,先补补基础知识。🤣

    参考

    相关文章

      网友评论

        本文标题:Alamofire源码分析笔记

        本文链接:https://www.haomeiwen.com/subject/ppamyxtx.html