Swift - Alamofire源码解析
Posted iOS_developer_zhong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift - Alamofire源码解析相关的知识,希望对你有一定的参考价值。
文章目录
Alamofire源码解析
解析版本: Alamofire V4.8.0
在使用Swift开发过程中,大家肯定都接触过这个网络请求框架,让我们的网络请求任务变得容易, 这个框架非常简单好用也易于封装,也会基于这个框架做一些自己的封装,比如加上自己的缓存方案等。本篇博客开始对他的源码进行一个解析,不到位处勿喷!!!
一、Alamofire目录结构
一共有17个类。 我会着重其中几个核心的地方,进行一个源码探索。
上面的17个类是什么意思呢,大概说下:
文件 | 作用 |
---|---|
AFError | 错误处理、错误合集、错误分类 |
Alamofire | 对外的请求入口,请求、下载、上传、多文件上传 |
DispatchQueue+Alamofire | 队列的扩展 |
MultipartFormData | 多表单数据处理 |
NetworkReachabilityManager | 网络环境监测工具 |
Notifications | 通知名称列举 |
ParameterEncoding | URL、JSON、PropertyList Encoding编码处理 |
Request | 定义请求类型,(普通,上传,多文件上传,下载) |
Response | 响应数据处理 |
ResponseSerialization | 响应数据的序列化 |
Result | 结果枚举类,请求结果的成功或者失败 |
ServerTrustPolicy | 证书验证类,解决客户端与服务器的信任问题 |
SessionDelegate | 处理Session的回调 |
SessionManager | 创建各种请求(普通,上传,多文件上传,下载) |
TaskDelegate | 定义多重Delegate,处理URLSessionTask delegate回调 |
Timeline | 负责请求中时间节点的处理 |
Validation | 验证请求的方式 (比如根据返回的code,判定成功) |
二、使用的基本流程 (不讲解基本使用,从源码解析)
基本网络请求使用的代码:
// request,根据项目的需求去组装请求的内容后,生成的 URLRequest
Alamofire.request(request).responseJSON(completionHandler: (response) in
1. 发起请求的源码 (举例:普通请求流程)
// 普通请求
public func request(
_ url: URLConvertible,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil)
-> DataRequest
return SessionManager.default.request(
url,
method: method,
parameters: parameters,
encoding: encoding,
headers: headers
)
- 当我们发起一个普通请求后,就会调用Alamofire类中定义的 request方法,当然不止这一个方法,还有 download, upload, stream等方法, 返回的结果是 SessionManager所管理的,根据调用的方法不同,依次返回的对象为: DataRequest, DownloadRequest, UploadRequest, StreamRequest。
- 源码中 : SessionManager.default , default 这是个单例对象, 这个对象很重要, 里面做了很多重要的工作。
2. SessionManager 的关键点解析
// 单例
public static let `default`: SessionManager =
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
return SessionManager(configuration: configuration)
()
// 初始化做了那些工作
public init(
configuration: URLSessionConfiguration = URLSessionConfiguration.default,
delegate: SessionDelegate = SessionDelegate(),
serverTrustPolicyManager: ServerTrustPolicyManager? = nil)
//1. 自己的delegate指向为新建的SessionDelegate()
self.delegate = delegate
//2. 创建一个URLSession , 并将 URLSession的代理指向了 SessionDelegte
self.session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
commonInit(serverTrustPolicyManager: serverTrustPolicyManager)
private func commonInit(serverTrustPolicyManager: ServerTrustPolicyManager?)
session.serverTrustPolicyManager = serverTrustPolicyManager
// 3. sessionDelegate 的 sessionManager 又指回了当前self, 它的内部 sessionManager为 weak,不然会有循环引用的问题,
delegate.sessionManager = self
delegate.sessionDidFinishEventsForBackgroundURLSession = [weak self] session in
guard let strongSelf = self else return
DispatchQueue.main.async strongSelf.backgroundCompletionHandler?()
通过上面的源码说明: 现在我们知道了
- URLSession的代理指向了 SessionDelegte
- sessionDelegate 的 Manager = 当前 sessionManager
这里使用了代理转换,每个类处理专门的事情。
3. SessionManager , 发起请求关键代码
@discardableResult
open func request(
_ url: URLConvertible,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil)
-> DataRequest
var originalRequest: URLRequest?
do
originalRequest = try URLRequest(url: url, method: method, headers: headers)
// 对参数进行编码
let encodedURLRequest = try encoding.encode(originalRequest!, with: parameters)
// 调用request请求
return request(encodedURLRequest)
catch
return request(originalRequest, failedWith: error)
/// - returns: The created `DataRequest`.
@discardableResult
open func request(_ urlRequest: URLRequestConvertible) -> DataRequest
var originalRequest: URLRequest?
do
//1. 返回 URLRequest 对象 ,判断为空的目的
originalRequest = try urlRequest.asURLRequest()
// 2. Requestable赋值, dataRequest继承与 request
let originalTask = DataRequest.Requestable(urlRequest: originalRequest!)
//3. task 为 URLSessionDataTask
let task = try originalTask.task(session: session, adapter: adapter, queue: queue)
// 4. 初始化DataRequest
let request = DataRequest(session: session, requestTask: .data(originalTask, task))
// 5. 用URLSessionTask的identity作为Key, dataRequest为value.
delegate[task] = request
// startRequestsImmediately 默认为true, 交于request中的task 开始执行网络请求
if startRequestsImmediately request.resume()
return request
catch
return request(originalRequest, failedWith: error)
// Request.swift文件中的
init(session: URLSession, requestTask: RequestTask, error: Error? = nil)
self.session = session
switch requestTask
case .data(let originalTask, let task):
// 1. 初始化DataTaskDelegate ,并指向给 taskDelegate
taskDelegate = DataTaskDelegate(task: task)
self.originalTask = originalTask
case .download(let originalTask, let task):
taskDelegate = DownloadTaskDelegate(task: task)
self.originalTask = originalTask
case .upload(let originalTask, let task):
taskDelegate = UploadTaskDelegate(task: task)
self.originalTask = originalTask
case .stream(let originalTask, let task):
taskDelegate = TaskDelegate(task: task)
self.originalTask = originalTask
delegate.error = error
delegate.queue.addOperation self.endTime = CFAbsoluteTimeGetCurrent()
大致流程为:
初始化 DataRequest ,并将 URLSession 指向 DataRequest,初始化DataTaskDelegate,指向 DataTaskDelegate的taskDelegate , 然后 SessionDelegate 以URLSessionDataTask的identity做为key,DataRequest作为value存储起来。 然后 交于request中的task 开始执行网络请求。
4. SessionDelegate , 收到请求关键代码
open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
if let dataTaskDidReceiveData = dataTaskDidReceiveData
dataTaskDidReceiveData(session, dataTask, data)
else if let delegate = self[dataTask]?.delegate as? DataTaskDelegate // 根据task的 indentity,获取到 taskDelegate ,然后执行接收到数据
delegate.urlSession(session, dataTask: dataTask, didReceive: data)
// 已经完成了本次网络请求,所调用的方法
open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
let completeTask: (URLSession, URLSessionTask, Error?) -> Void = [weak self] session, task, error in
guard let strongSelf = self else return
// 1. 执行这个闭包
strongSelf.taskDidComplete?(session, task, error)
// 2. 执行TaskDelegate中的urlsession ,里面逻辑是和下载有关。
strongSelf[task]?.delegate.urlSession(session, task: task, didCompleteWithError: error)
var userInfo: [String: Any] = [Notification.Key.Task: task]
// 3. 拿到TaskDelegate中的 data (mutableData)
if let data = (strongSelf[task]?.delegate as? DataTaskDelegate)?.data
userInfo[Notification.Key.ResponseData] = data
// 4. 暂时没有用到,通过通知把数据发送出去,使用者去监听这个通知可拿到数据
NotificationCenter.default.post(
name: Notification.Name.Task.DidComplete,
object: strongSelf,
userInfo: userInfo
)
strongSelf[task] = nil
// 出错处理。
guard let request = self[task], let sessionManager = sessionManager else
completeTask(session, task, error)
return
if let retrier = retrier, let error = error
/* 省略若干代码*/
else
// 执行上面的block
completeTask(session, task, error)
- SessionDelegate 接收到服务器数据返回后, 就会交于到 taskDelegate, 这个delegate,也是第三点中, 通过task的identity,存储到 sessionDelegate中, 这时候再拿出来对应的 taskDelegate 。
5. TaskDelegate , 收到请求的关键代码
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
if initialResponseTime == nil initialResponseTime = CFAbsoluteTimeGetCurrent()
if let dataTaskDidReceiveData = dataTaskDidReceiveData
dataTaskDidReceiveData(session, dataTask, data)
else
if let dataStream = dataStream
dataStream(data)
else // 1. 把接收到的数据放到了mutableData成员变量中。
mutableData.append(data)
// 进度计算, 暂时不管
let bytesReceived = Int64(data.count)
totalBytesReceived += bytesReceived
let totalBytesExpected = dataTask.response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown
progress.totalUnitCount = totalBytesExpected
progress.completedUnitCount = totalBytesReceived
if let progressHandler = progressHandler
progressHandler.queue.async progressHandler.closure(self.progress)
5. 数据序列化的工作。 ResponseSerialization类,关键代码
public static func serializeResponseJSON(
options: JSONSerialization.ReadingOptions,
response: HTTPURLResponse?,
data: Data?,
error: Error?)
-> Result<Any>
guard error == nil else return .failure(error!)
// 1. 判断数据是否为空, 根据状态码
if let response = response, emptyDataStatusCodes.contains(response.statusCode) return .success(NSNull())
//2. 判断数据是否为空,根据内容长度
guard let validData = data, validData.count > 0 else
return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength))
do //3. data转json 数据。
let json = try JSONSerialization.jsonObject(with: validData, options: options)
//4.回调转化成json数据给调用者
return .success(json)
catch
return .failure(AFError.responseSerializationFailed(reason: .jsonSerializationFailed(error: error)))
我们在来回顾下调用方法,
// request,根据项目的需求去组装请求的内容后,生成的 URLRequest
Alamofire.request(request).responseJSON(completionHandler: (response) in
这里可能有个疑问,为什么这里可以使用链式调用, 这里因为 Alamofire.request(request) 返回的是一个DataRequest对象,而responseJSON,是对DataRequest的扩展,所以可以直接调用。
总结
上面说的还很绕的,我通过打断点,追流程,大概总结下,发送一个普通请求,到底经过了那些步骤
- Alamofire.swift 文件中的方法 ,对外的request方法
@discardableResult
public func request(_ urlRequest: URLRequestConvertible) -> DataRequest
- SessionManager.swift文件中的方法 ,内部的 request方法
@discardableResult
open func request(_ urlRequest: URLRequestConvertible) -> DataRequest
- request.swift文件中的方法 ,发送request网络请求
open func resume()
- SessionDelegate.swift文件中的方法, 网络回调数据
open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
- TaskDelegate.swift文件中的方法, 数据存储,进度计算
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
- SessionDelegate.swift 文件中的方法, 本次网络请求结束 ,相关的处理
open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
- ResponseSerialization.swift文件中的方法 , 数据的序列化处理
public static func jsonResponseSerializer(
options: JSONSerialization.ReadingOptions = .allowFragments)
-> DataResponseSerializer<Any>
- 处理好的json数据 闭包 ( Result : 成功或者失败)传递给调用者。
上面有个疑问? 网络数据完毕后,是如何跑到序列化闭包里面,并返回数据?
这里用到了队列,提前将网络数据装入了队列中,网络数据接收完毕后,再调用起队列,执行任务。
核心的位置: 除了delegate任务分离外, 还有 队列任务用的很巧妙。
在还没有收到网络数据返回前,就将response里面的相关数据, 以闭包的方式加入到 OperationQueue ,代码如下:
//1. TaskDelegate.swift OperationQueue的初始化, 默认任务是挂起的, 这里很重要
init(task: URLSessionTask?)
_task = task
self.queue =
let operationQueue = OperationQueue()
operationQueue.maxConcurrentOperationCount = 1
// 1. 默认任务挂起
operationQueue.isSuspended = true
operationQueue.qualityOfService = .utility
return operationQueue
()
// 2. ResponseSerialization.swift中把 response相关数据打包成block,并放入队列中,等待后面队列的调用。
@discardableResult
public func response<T: DataResponseSerializerProtocol>(
queue: DispatchQueue? = nil,
responseSerializer: T,
completionHandler: @escaping (DataResponse<T.SerializedObject>) -> Void)
-> Self
//
delegate.queue.addOperation
let result = responseSerializer.serializeResponse(
self.request,
self.response,
self.delegate.data,
self.delegate.error
)
var dataResponse = DataResponse<T.SerializedObject>(
request: self.request,
response: self.response,
data: self.delegate.data,
result: result,
timeline: self.timeline
)
dataResponse.add(self.delegate.metrics)
(queue ?? DispatchQueue.main).async completionHandler(dataResponse)
return self
// 3. 队列的激活, SessionDelegate 中调用完成本次网络请求的回调方法中调用了 TaskDelegate
// sessionDelegate.swift 网络返回数据结束
```swift
open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
// TaskDelegate.swift 激活队列
@objc(URLSession以上是关于Swift - Alamofire源码解析的主要内容,如果未能解决你的问题,请参考以下文章
swift、Alamofire、SwiftyJSON:如何解析 arrayObject
在 Swift 中将 Alamofire 结果解析为对象(使用:Alamofire、SwiftyJSON 和 ObjectMapper)