/// Reference to `Session.default` for quick bootstrapping and examples.
public let AF = Session.default
/// Current Alamofire version. Necessary since SPM doesn't use dynamic libraries. Plus this will be more accurate.
let version = "5.4.0"
复制代码
就这两个常量, 一个是Session类的一个单例, 一个标记了当前版本号.bootstrap
/// 一个默认的单例
public static let `default` = Session()
/// 持有一个URLSession, 用来建立请求Task, 注意不能跟本对象持有的URLSessionTask产生交互, 不然会影响Alamofire内部逻辑
public let session: URLSession
/// 处理URLSession代理, URLSessionTaskDelegate, 以及请求拦截等逻辑
public let delegate: SessionDelegate
/// 内部回调执行以及状态更新的队列,必须是串行队列
public let rootQueue: DispatchQueue
/// 是否在Request建立的时候就马上发送, 该属性用来统一管理Request建立时的startImmediately参数, 默认true
public let startRequestsImmediately: Bool
/// 异步建立Request的队列,默认是rootQueue
public let requestQueue: DispatchQueue
/// 解析response的队列, 默认是rootQueue
public let serializationQueue: DispatchQueue
/// 请求拦截器接口,是RequestAdapter跟RequestRetrier的结合, 默认nil
public let interceptor: RequestInterceptor?
/// 证书信任器接口, 默认nil
public let serverTrustManager: ServerTrustManager?
/// 重定向处理器接口, 默认nil
public let redirectHandler: RedirectHandler?
/// 缓存管理接口, 默认nil
public let cachedResponseHandler: CachedResponseHandler?
/// 事件监测管理器类,处理请求生命周期各阶段的事件, 默认用下面的defaultEventMonitors以及传入的事件检测器初始化
public let eventMonitor: CompositeEventMonitor
/// 默认的事件监测器接口列表,只有一个通知事件监测器
public let defaultEventMonitors: [EventMonitor] = [AlamofireNotifications()]
/// 结构体, 用来保存Request跟URLSessiontask映射关系, 提供了各类方法来存取task跟request以及数量判断, 为空判断
var requestTaskMap = RequestTaskMap()
/// 当前正在请求的Request集合
var activeRequests: Set<Request> = []
/// 等待成功的回调
var waitingCompletions: [URLSessionTask: () -> Void] = [:]
复制代码
Session有两个初始化方法, 一个必要初始化方法, 一个便捷初始化方法.swift
public init(session: URLSession, delegate: SessionDelegate, rootQueue: DispatchQueue, startRequestsImmediately: Bool = true, requestQueue: DispatchQueue? = nil, serializationQueue: DispatchQueue? = nil, interceptor: RequestInterceptor? = nil, serverTrustManager: ServerTrustManager? = nil, redirectHandler: RedirectHandler? = nil, cachedResponseHandler: CachedResponseHandler? = nil, eventMonitors: [EventMonitor] = []) {
// Alamofire不支持后台下载(为啥嘞?看后面是支持的)
precondition(session.configuration.identifier == nil,
"Alamofire does not support background URLSessionConfigurations.")
// URLSession的Queue跟rootQueue必须同样
precondition(session.delegateQueue.underlyingQueue === rootQueue,
"Session(session:) initializer must be passed the DispatchQueue used as the delegateQueue's underlyingQueue as rootQueue.")
self.session = session
self.delegate = delegate
self.rootQueue = rootQueue
self.startRequestsImmediately = startRequestsImmediately
// 默认用rootQueue作target建立请求响应解析队列
self.requestQueue = requestQueue ?? DispatchQueue(label: "\(rootQueue.label).requestQueue", target: rootQueue)
self.serializationQueue = serializationQueue ?? DispatchQueue(label: "\(rootQueue.label).serializationQueue", target: rootQueue)
// 四个默认nil的属性
self.interceptor = interceptor
self.serverTrustManager = serverTrustManager
self.redirectHandler = redirectHandler
self.cachedResponseHandler = cachedResponseHandler
// 根据传入的事件监听器以及默认的监听器初始化CompositeEventMonitor对象
eventMonitor = CompositeEventMonitor(monitors: defaultEventMonitors + eventMonitors)
// 把组合监听器对象丢给SessionDelegate对象用来管理task
delegate.eventMonitor = eventMonitor
// 请求时Session变化的处理
delegate.stateProvider = self
}
复制代码
便捷初始化方法使用了默认的URLSessionConfiguration以及请求队列来初始化URLSession, SessionDelegate, rootQueueapi
deinit {
finishRequestsForDeinit()
session.invalidateAndCancel()
}
func finishRequestsForDeinit() {
//挨个通知还没完成的Request 返回sessionDeinitialized错误
requestTaskMap.requests.forEach { request in
rootQueue.async {
request.finish(error: AFError.sessionDeinitialized)
}
}
}
复制代码
//对全部正在执行的请求执行一个闭包
public func withAllRequests(perform action: @escaping (Set<Request>) -> Void) {
rootQueue.async {
action(self.activeRequests)
}
}
//取消所有请求
public func cancelAllRequests(completingOnQueue queue: DispatchQueue = .main, completion: (() -> Void)? = nil) {
withAllRequests { requests in
requests.forEach { $0.cancel() }
queue.async {
completion?()
}
}
}
复制代码
先定义了RequestConvertible与RequestEncodableConvertible结构体实现URLRequestConvertible协议, 用来使用不一样参数建立URLRequestConvertible对象缓存
// 用来变换URLRequest对象的闭包
public typealias RequestModifier = (inout URLRequest) throws -> Void
//普通的request转换器, 使用ParameterEncoding协议对象来编码参数
struct RequestConvertible: URLRequestConvertible {
let url: URLConvertible//url
let method: HTTPMethod//方法
let parameters: Parameters?//参数
let encoding: ParameterEncoding//参数编码对象, 默认URL编码
let headers: HTTPHeaders?//请求头
let requestModifier: RequestModifier?
}
//参数符合Encodable协议的转换器, 使用ParameterEncoder协议对象编码参数
struct RequestEncodableConvertible<Parameters: Encodable>: URLRequestConvertible {
let url: URLConvertible
let method: HTTPMethod
let parameters: Parameters?
let encoder: ParameterEncoder
let headers: HTTPHeaders?
let requestModifier: RequestModifier?
}
复制代码
对于普通request, streamRequest, downloadRequest, 都有三个建立请求的方法:sass
- 先使用参数建立RequestConvertible对象, 而后转换为URLRequestConvertible后使用3来建立对应的Request对象
- 使用RequestConvertible建立, 逻辑同1
- 使用URLRequestConvertible对象+rootQueue+serializationQueue+eventMonitor建立Request对象, 并指定RequestDelegate为self用来处理URLSessionConfiguration, 清理工做以及重试逻辑
- downloadRequest有一个额外的断点续传的方法, 使用已下载的Data来初始化DownloadRequest对象
对于UploadRequest, 又定义了ParameterlessRequestConvertible结构体实现URLRequestConvertible协议, 特色是没有参数.
接着定义Upload结构体实现UploadConvertible用来封装request与uploadable
对于UploadRequest的建立使用的都是ParameterlessRequestConvertible对象, 有共计X个建立UploadRequest的方法:安全
- 使用data + 请求基础参数, 先生成ParameterlessRequestConvertible对象,转2
- 使用data, URLRequestConvertible对象, 生成Uploadable.data对象, 转11
- 使用fileURL + 请求基础参数, 先生成ParameterlessRequestConvertible对象, 转4
- 使用fileURL, ParameterlessRequestConvertible对象, 生成Uploadable.file对象, 转11
- 使用InputStream + 基础参数 转6
- 使用InputStream, ParameterlessRequestConvertible, 生成Uploadable.stream对象,转11
- 使用多表单闭包+请求基础参数, 执行闭包生成MultipartFormData, ParameterlessRequestConvertible, 转换为URLRequestConvertible, 转10
- 使用多表单闭包+URLRequestConvertible, 执行闭包, 转10
- 使用MultipartFormData对象+基础请求参数, 生成ParameterlessRequestConvertible, MultipartUpload, 转12
- 使用MultipartFormData对象+URLRequestConvertible生成MultipartUpload, 转12
- 如下为intenal api, 外部没法访问
- 使用Uploadable + URLRequestConvertible, 生成Upload, 转12 (在Session中未用到)
- 使用UploadConvertible协议对象生成UploadRequest并发送
注意:
- upload方法共有12个, 本质上upload方法分为3种: data(内存), fileURL(磁盘), InputStream(磁盘), 7-10均为处理多表单数据, 参数中带有一个encodingMemoryThreshold参数, 用来决定编码内存限制, 当表单数据大小大于该限制时, 编码将把表单数据存到磁盘, 使用iostream来处理, 避免内存太高. 生成的Uploadable的类型根据表单编码类型来肯定.
- 全部的upload的url都没有query参数, 因此用的是ParameterlessRequestConvertible结构体来转换URLRequestConvertible协议对象.
- upload的12个方法 都是互相调用, 最终的数据编码, 都在对应的Request模块
主入口为:markdown
// MARK: Perform
/// Starts performing the provided `Request`.
///
/// - Parameter request: The `Request` to perform.
func perform(_ request: Request) {
rootQueue.async {
//先在rootQueue中判断是否请求被取消
guard !request.isCancelled else { return }
//塞入到正在请求的Request集合中
self.activeRequests.insert(request)
//在requestQueue队列发送请求
self.requestQueue.async {
// 子类必须先case不然就会被识别为父类了
switch request {
case let r as UploadRequest:
// UploadRequest是DataRequest的子类
self.performUploadRequest(r)
//先建立Uploadable
//而后在rootQueue告知事件监听器didCreateUploadable, 而后调用performSetupOperations方法
//建立失败的话先在rootQueue告知监视器didFailToCreateUploadable, 错误消息为createUploadableFailed
//而后在request中决定是否重试
case let r as DataRequest:
self.performDataRequest(r)
//直接调performSetupOperations方法
case let r as DownloadRequest:
self.performDownloadRequest(r)
//对request的downloadable进行断定
//若是是新建下载, 直接调用performSetupOperations方法
//若是是断点续传, 在rootQueue调用didReceiveResumeData方法, 详见下方断点续传部分
case let r as DataStreamRequest:
self.performDataStreamRequest(r)
//直接调performSetupOperations方法
default:
fatalError("Attempted to perform unsupported Request subclass: \(type(of: request))")
}
}
}
}
复制代码
方法performSetupOperations接受两个参数: Request对象以及URLRequestConvertible协议对象, 后者来自于request.convertible属性. 处理成功后, 会调用didCreateURLRequest方法来更新状态session
func performSetupOperations(for request: Request, convertible: URLRequestConvertible) {
//当前在requestQueue
dispatchPrecondition(condition: .onQueue(requestQueue))
//URLRequestConvertible生成的URLRequest
let initialRequest: URLRequest
do {
initialRequest = try convertible.asURLRequest()
//检测请求是否有效(get请求不能带body参数)
try initialRequest.validate()
} catch {
//出错的话就在rootQueue队列上报错误
rootQueue.async { request.didFailToCreateURLRequest(with: error.asAFError(or: .createURLRequestFailed(error: error))) }
return
}
//在rootQueue通知request,初始化URLRequest成功(使用MutableState记录状态, 告知事件监听器didCreateInitialURLRequest)
rootQueue.async { request.didCreateInitialURLRequest(initialRequest) }
guard !request.isCancelled else { return }
//检查是否有请求适配器, 内部逻辑:
//1. 判断request的拦截器跟Session的拦截器都不为空的话, 就返回生成组合拦截器
//2. 返回request拦截器或者Session拦截器
guard let adapter = adapter(for: request) else {
//没有拦截器的话直接通知
rootQueue.async { self.didCreateURLRequest(initialRequest, for: request) }
return
}
//使用拦截器中的适配器来预处理请求
adapter.adapt(initialRequest, for: self) { result in
do {
let adaptedRequest = try result.get()
try adaptedRequest.validate()
//通知处理完成
self.rootQueue.async {
request.didAdaptInitialRequest(initialRequest, to: adaptedRequest)
self.didCreateURLRequest(adaptedRequest, for: request)
}
} catch {
//任何错误都抛出requestAdaptationFailed错误
self.rootQueue.async { request.didFailToAdaptURLRequest(initialRequest, withError: .requestAdaptationFailed(error: error)) }
}
}
}
复制代码
当建立请求完成, 拦截适配器处理完成以后, 就会来到这里的逻辑, 除了断点续传的请求会执行didReceiveResumeData方法, 其余的几个请求都会执行didCreateURLRequest方法, 而后最终都会调用updateStatesForTask方法来更新闭包
func didCreateURLRequest(_ urlRequest: URLRequest, for request: Request) {
dispatchPrecondition(condition: .onQueue(rootQueue))
//通知建立request成功
request.didCreateURLRequest(urlRequest)
guard !request.isCancelled else { return }
//建立URLSessionTask, 基类Request为实现该方法, 几个子类各自实现
let task = request.task(for: urlRequest, using: session)
//写入Session的Request-Task数据对里保存
requestTaskMap[request] = task
//建立URLSessionTask成功后, request作的相关处理, 线程安全地保存task, 并通知事件监听器建立task成功
request.didCreateTask(task)
updateStatesForTask(task, request: request)
}
//基本逻辑跟上面类似, 区别就是建立task的方法不一样, 使用已下载Data建立URLSessionDownloadTask
func didReceiveResumeData(_ data: Data, for request: DownloadRequest) {
dispatchPrecondition(condition: .onQueue(rootQueue))
guard !request.isCancelled else { return }
let task = request.task(forResumeData: data, using: session)
requestTaskMap[request] = task
request.didCreateTask(task)
updateStatesForTask(task, request: request)
}
//上面两个方法完成后会调用该方法, 开始开始发送请求
func updateStatesForTask(_ task: URLSessionTask, request: Request) {
//确认是在rootQueue队列更新URLSessionTask的状态
dispatchPrecondition(condition: .onQueue(rootQueue))
//根据request的状态来更新对应task的状态
request.withState { state in
switch state {
case .initialized, .finished:
// 初始化或者请求完成, 啥也不干
break
case .resumed:
//发送请求
task.resume()
//告知request task开始请求
rootQueue.async { request.didResumeTask(task) }
case .suspended:
//请求挂起
task.suspend()
rootQueue.async { request.didSuspendTask(task) }
case .cancelled:
//先恢复task 再取消, 保证task被取消
task.resume()
task.cancel()
rootQueue.async { request.didCancelTask(task) }
}
}
}
复制代码
而后等待request各自的RequestDelegate去处理请求落地的逻辑便可
//这两个逻辑都同样, 使用 Interceptor 类来组合Session默认的以及每一个请求单独的 适配器/重试器
func adapter(for request: Request) -> RequestAdapter? {
if let requestInterceptor = request.interceptor, let sessionInterceptor = interceptor {
return Interceptor(adapters: [requestInterceptor, sessionInterceptor])
} else {
return request.interceptor ?? interceptor
}
}
func retrier(for request: Request) -> RequestRetrier? {
if let requestInterceptor = request.interceptor, let sessionInterceptor = interceptor {
return Interceptor(retriers: [requestInterceptor, sessionInterceptor])
} else {
return request.interceptor ?? interceptor
}
}
复制代码
每个Request对象都持有一个RequestDelegate代理对象用来获取建立Request时的URLSessionConfiguration以及全局startImmediately, 而且处理错误重试与延迟重试逻辑, 指向建立Request的Session, 所以在Session中实现了RequestDelegate协议
Session持有SessionDelegate用来处理Task的代理, SessionDelegate又持有一个RequestTaskMap代理指向Session, 来处理当Task状态变动时的状态处理(由于Session持有一个RequestTaskMap对象来储存Request跟NSURLSessionTask的映射关系), 所以当SessionDelegate响应URLSessionDelegate以及各个NSURLSessionTask的代理回调时, 会回调到Session中的SessionStateProvider相关协议方法中,来根据Task取得对应的Request, 并判断是否请求完成断开映射关系。
//全部操做都在rootQueue进行
extension Session: SessionStateProvider {
func request(for task: URLSessionTask) -> Request? {
dispatchPrecondition(condition: .onQueue(rootQueue))
//根据task获取Request
return requestTaskMap[task]
}
func didGatherMetricsForTask(_ task: URLSessionTask) {
dispatchPrecondition(condition: .onQueue(rootQueue))
//task成功获取任务指标后的行为
//在RequestTaskMap结构体中处理, 检测是否须要断开request跟task的连接
let didDisassociate = requestTaskMap.disassociateIfNecessaryAfterGatheringMetricsForTask(task)
//waitingCompletions闭包来自于task请求成功后设置的后续操做, 若是成功获取任务指标后, 执行后续操做, 至此请求完成
if didDisassociate {
waitingCompletions[task]?()
waitingCompletions[task] = nil
}
}
func didCompleteTask(_ task: URLSessionTask, completion: @escaping () -> Void) {
dispatchPrecondition(condition: .onQueue(rootQueue))
//检测是否须要断开request跟task的连接
let didDisassociate = requestTaskMap.disassociateIfNecessaryAfterCompletingTask(task)
//若是没有后续逻辑, 直接执行完成回调, 不然把回调保存在waitingCompletions字典中, 等待检查任务指标后再判断是否要断开连接
if didDisassociate {
completion()
} else {
waitingCompletions[task] = completion
}
}
func credential(for task: URLSessionTask, in protectionSpace: URLProtectionSpace) -> URLCredential? {
dispatchPrecondition(condition: .onQueue(rootQueue))
//HTTPS证书处理
return requestTaskMap[task]?.credential ??
session.configuration.urlCredentialStorage?.defaultCredential(for: protectionSpace)
}
func cancelRequestsForSessionInvalidation(with error: Error?) {
dispatchPrecondition(condition: .onQueue(rootQueue))
//当URLSession出错时, 并抛出错误
requestTaskMap.requests.forEach { $0.finish(error: AFError.sessionInvalidated(error: error)) }
}
}
复制代码
我的理解记录~若有错误欢迎评论指出,很是感谢~