往期导航:
简介:
Request类是Alamofire中对URLRequest以及URLSessionTask的封装,持有多个请求参数, 请求状态, 代理对象, 以及一些回调. Request类为基类, 不直接使用, 而是用派生的四个子类来执行请求逻辑:
- DataRequest: 使用URLSessionDataTask处理普通请求
- DataStreamRequest: 处理流式请求
- DownloadRequest: 使用URLSessionDownloadTask处理下载请求
- UploadRequest: 使用URLSessionUploadTask处理上传请求
但是对外的接口统一都为Request对象. 在操作Request对象时会先进性类型判定.
Request基类:
State枚举:
用来描述Request当前的状态, 当调用resume(), suspend(), cancel()等方法时, 会判断能否变更状态并更新状态, 同时会更新自己所关联的task的状态
public enum State {
case initialized //Request初始状态
case resumed //调用resume()的时候更新为该状态, 同时对所有自己创建的task调用resume()方法
case suspended //类似上面resumed
case cancelled //类似上面, 不同的是: 一旦调用了cancelled, Request就不再能转变为其他状态了
case finished //当响应解析全部完成, 并且回调被清除后更新为该状态
/// 判断当前状态是否能转换为新的状态
func canTransitionTo(_ state: State) -> Bool {
switch (self, state) {
case (.initialized, _):
return true //初始状态可以变换为任何状态
case (_, .initialized), (.cancelled, _), (.finished, _):
return false //任何状态不能转换为初始状态, 取消,完成状态不能转换为其他状态
case (.resumed, .cancelled), (.suspended, .cancelled), (.resumed, .suspended), (.suspended, .resumed):
return true //互相可以转换的状态
case (.suspended, .suspended), (.resumed, .resumed):
return false //挂起与继续状态不能转换为自身
case (_, .finished):
return true //任何状态(除了cancelled,finished)可以直接转为完成状态
}
}
}
初始化时定义的初始属性
Request初始化时, 会初始化5个常量属性以及一个weak变量RequestDelegate:
/// 唯一id, 用来实现Hashable以及Equatable协议
public let id: UUID
/// 内部异步操作执行的队列
public let underlyingQueue: DispatchQueue
/// 响应解析的队列, 默认为underlyingQueue
public let serializationQueue: DispatchQueue
/// 事件监听器
public let eventMonitor: EventMonitor?
/// 请求拦截器
public let interceptor: RequestInterceptor?
/// RequestDelegate(指向Session)
public private(set) weak var delegate: RequestDelegate?
线程安全的属性:MutableState
Request定义了一个结构体:MutableState, 包括各种需要线程安全的属性
struct MutableState {
/// Request状态
var state: State = .initialized
/// 上传进度回调以及该回调所调用的队列
var uploadProgressHandler: (handler: ProgressHandler, queue: DispatchQueue)?
/// 下载进度回调以及队列
var downloadProgressHandler: (handler: ProgressHandler, queue: DispatchQueue)?
/// 重定向处理协议对象
var redirectHandler: RedirectHandler?
/// 缓存处理协议对象
var cachedResponseHandler: CachedResponseHandler?
/// 当Request支持创建curl时, 该属性持有创建curl的回调以及调用队列
var cURLHandler: (queue: DispatchQueue, handler: (String) -> Void)?
/// Request创建URLRequest成功后的回调以及调用队列
var urlRequestHandler: (queue: DispatchQueue, handler: (URLRequest) -> Void)?
/// Request创建Task成功后的回调以及调用队列
var urlSessionTaskHandler: (queue: DispatchQueue, handler: (URLSessionTask) -> Void)?
/// 存放响应解析回调的数组
var responseSerializers: [() -> Void] = []
/// 存放响应解析完成回调的数组
var responseSerializerCompletions: [() -> Void] = []
/// 响应解析是否完成
var responseSerializerProcessingFinished = false
/// http请求认证证书
var credential: URLCredential?
/// 所有被Request对象创建的URLRequest对象数组
var requests: [URLRequest] = []
/// 所有被Request对象创建的URLSessionTask对象数组
var tasks: [URLSessionTask] = []
/// 所有task数组对应的请求指标
var metrics: [URLSessionTaskMetrics] = []
/// 当前重试次数
var retryCount = 0
/// 最终抛出的错误, 可能是Alamofire内部抛出的错误(证书认证失败), 可能是请求失败
var error: AFError?
/// 是否调用了finish()方法, 跟State中的finished一致
var isFinishing = false
}
定义以上属性后, Request持有一个使用@Protected修饰的私有属性变量mutableState来保证修改这些属性时是线程安全的:
@Protected修饰器将在后面文章讲解
@Protected
//私有的线程安全属性, 后面声明了几个计算属性来从这个属性里获取各个参数
fileprivate var mutableState = MutableState()
//接着声明了几个计算属性, 快速从mutableState中取各种状态:
//State属性
public var state: State { mutableState.state }
//几个判断计算属性:
public var isInitialized: Bool { state == .initialized }
public var isResumed: Bool { state == .resumed }
public var isSuspended: Bool { state == .suspended }
public var isCancelled: Bool { state == .cancelled }
public var isFinished: Bool { state == .finished }
/// 监听器监听进度时的回调类型
public typealias ProgressHandler = (Progress) -> Void
/// 上传进度, retry时会被还原成0
public let uploadProgress = Progress(totalUnitCount: 0)
/// 下载进度, retry时会被还原成0
public let downloadProgress = Progress(totalUnitCount: 0)
/// 线程安全的上传进度回调与调用的queue
fileprivate var uploadProgressHandler: (handler: ProgressHandler, queue: DispatchQueue)? {
get { mutableState.uploadProgressHandler }
set { mutableState.uploadProgressHandler = newValue }
}
/// 线程安全的下载进度回调与队列
fileprivate var downloadProgressHandler: (handler: ProgressHandler, queue: DispatchQueue)? {
get { mutableState.downloadProgressHandler }
set { mutableState.downloadProgressHandler = newValue }
}
// MARK: 重定向处理
/// 线程安全的重定向处理协议对象
public private(set) var redirectHandler: RedirectHandler? {
get { mutableState.redirectHandler }
set { mutableState.redirectHandler = newValue }
}
// MARK: Cached Response Handling
/// 线程安全的缓存处理协议对象
public private(set) var cachedResponseHandler: CachedResponseHandler? {
get { mutableState.cachedResponseHandler }
set { mutableState.cachedResponseHandler = newValue }
}
// MARK: http认证证书
/// 线程安全的证书对象, 在调用authenticate相关方法的时候创建
public private(set) var credential: URLCredential? {
get { mutableState.credential }
set { mutableState.credential = newValue }
}
// MARK: Validators
/// 线程安全的检测响应有效性的回调数组
@Protected
fileprivate var validators: [() -> Void] = []
// MARK: URLRequest相关
/// 线程安全的URLRequest数组, 包括原始URLRequest以及适配器处理过的URLReqeust
public var requests: [URLRequest] { mutableState.requests }
/// 第一个创建的URLRequest, 可能并不是第一个发出请求
public var firstRequest: URLRequest? { requests.first }
/// 最后一个创建的URLRequest
public var lastRequest: URLRequest? { requests.last }
/// 当前URLRequest(当前最后的一个)
public var request: URLRequest? { lastRequest }
/// 创建的URLSessionTask的URLRequest数组, 可能跟requests属性不一样, 因为requests包括了原始请求以及适配器处理过后的请求
public var performedRequests: [URLRequest] { $mutableState.read { $0.tasks.compactMap { $0.currentRequest } } }
// MARK: HTTPURLResponse响应相关
/// 服务器返回的响应, 如果请求重试了, 该属性为最后的task的响应
public var response: HTTPURLResponse? { lastTask?.response as? HTTPURLResponse }
// MARK: Tasks相关
/// 线程安全的task数组
public var tasks: [URLSessionTask] { mutableState.tasks }
/// 第一个创建task
public var firstTask: URLSessionTask? { tasks.first }
/// 最后一个创建的
public var lastTask: URLSessionTask? { tasks.last }
/// 当前的task(当前最后一个创建的task)
public var task: URLSessionTask? { lastTask }
// MARK: Metrics请求指标
/// 线程安全的请求指标数组
public var allMetrics: [URLSessionTaskMetrics] { mutableState.metrics }
/// 第一个请求到的
public var firstMetrics: URLSessionTaskMetrics? { allMetrics.first }
/// 最后一个请求到的
public var lastMetrics: URLSessionTaskMetrics? { allMetrics.last }
/// 当前的请求指标(当前最后一个请求到的指标)
public var metrics: URLSessionTaskMetrics? { lastMetrics }
// MARK: 重试次数
/// 已经重试过的次数
public var retryCount: Int { mutableState.retryCount }
// MARK: 错误相关
/// 线程安全的抛出错误
public fileprivate(set) var error: AFError? {
get { mutableState.error }
set { mutableState.error = newValue }
}
内部api, 只允许Alamofile模块内部调用, 模块外部无法调用:
主要为请求过程中的状态变化通知
// MARK: - 内部事件api 所有api都必须在underlyingQueue队列中执行
/// 当原始URLRequest对象被创建成功后调用(Session中调用)
func didCreateInitialURLRequest(_ request: URLRequest) {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
//添加到requests数组
$mutableState.write { $0.requests.append(request) }
//通知监听器
eventMonitor?.request(self, didCreateInitialURLRequest: request)
}
/// 创建原始URLRequest对象失败时调用(Session中调用)
func didFailToCreateURLRequest(with error: AFError) {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
//记录错误
self.error = error
//通知监听器
eventMonitor?.request(self, didFailToCreateURLRequestWithError: error)
//调用下curl回调(在创建request完成前设置了curl回调, 会把回调存起来, 这时候创建
callCURLHandlerIfNecessary()
//重试或者直接抛出错误
retryOrFinish(error: error)
}
/// 适配器适配原始URLRequest成功后调用, 参数为原始URLRequest以及新的URLRequest(Session中调用)
func didAdaptInitialRequest(_ initialRequest: URLRequest, to adaptedRequest: URLRequest) {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
//添加到requests数组
$mutableState.write { $0.requests.append(adaptedRequest) }
//通知监听器
eventMonitor?.request(self, didAdaptInitialRequest: initialRequest, to: adaptedRequest)
}
/// 适配器处理请求失败时调用(Session中调用)
func didFailToAdaptURLRequest(_ request: URLRequest, withError error: AFError) {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
self.error = error
eventMonitor?.request(self, didFailToAdaptURLRequest: request, withError: error)
//调用下curl回调(在创建request完成前设置了curl回调, 会把回调存起来, 这时候创建
callCURLHandlerIfNecessary()
retryOrFinish(error: error)
}
/// 创建URLRequest完成时调用(适配器适配完成), 参数为适配器适处理过后的Request对象 (Session中调用)
func didCreateURLRequest(_ request: URLRequest) {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
$mutableState.read { state in
//执行state中的请求创建成功回调
state.urlRequestHandler?.queue.async { state.urlRequestHandler?.handler(request) }
}
eventMonitor?.request(self, didCreateURLRequest: request)
//调用下curl回调(在创建request完成前设置了curl回调, 会把回调存起来, 这时候创建
callCURLHandlerIfNecessary()
}
/// 异步调用之前存的curl回调 然后删掉已经调用过的回调
private func callCURLHandlerIfNecessary() {
$mutableState.write { mutableState in
guard let cURLHandler = mutableState.cURLHandler else { return }
cURLHandler.queue.async { cURLHandler.handler(self.cURLDescription()) }
mutableState.cURLHandler = nil
}
}
/// 创建URLSessionTask成功后调用(1. 直接创建task成功, 2. 创建断点续传task成功)(Session中调用)
func didCreateTask(_ task: URLSessionTask) {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
//添加到tasks数组, 然后调用下state里的创建task成功的回调
$mutableState.write { state in
state.tasks.append(task)
guard let urlSessionTaskHandler = state.urlSessionTaskHandler else { return }
urlSessionTaskHandler.queue.async { urlSessionTaskHandler.handler(task) }
}
eventMonitor?.request(self, didCreateTask: task)
}
/// 当Request对象调用resume()方法时调用 (自己调用, 外部调用request.resume()方法)
func didResume() {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
//通知监听器
eventMonitor?.requestDidResume(self)
}
/// URLSessionTask调用resume后调用(1. 自己调用了resume()方法会对task调用resume方法, 然后调该方法. 2.Session调用了updateStatesForTask方法来更新task的状态时会调用该方法)
func didResumeTask(_ task: URLSessionTask) {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
eventMonitor?.request(self, didResumeTask: task)
}
/// 调用suspend方法后调用该方法(自己调用)
func didSuspend() {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
eventMonitor?.requestDidSuspend(self)
}
/// task调用suspend方法后调用(1. 自己调用suspend方法后会调用task的suspend方法, 然后调用该方法. 2.Session调用了updateStatesForTask方法来更新task的状态时会调用该方法)
func didSuspendTask(_ task: URLSessionTask) {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
eventMonitor?.request(self, didSuspendTask: task)
}
/// 调用cancel()方法后调用(1. 直接取消, 2.提供一个已下载的data后再取消), 若此时error为nil, 会把error设置为AFError.explicitlyCancelled
func didCancel() {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
error = error ?? AFError.explicitlyCancelled
eventMonitor?.requestDidCancel(self)
}
/// task调用cancel方法后调用(1. 自己调用cancel方法后会调用task的cancel方法, 然后调用该方法. 2.Session调用了updateStatesForTask方法来更新task的状态时会调用该方法)
func didCancelTask(_ task: URLSessionTask) {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
eventMonitor?.request(self, didCancelTask: task)
}
/// task成功请求到请求指标后调用(SessionDelegate中通过stateProvider(Session)调用)
func didGatherMetrics(_ metrics: URLSessionTaskMetrics) {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
$mutableState.write { $0.metrics.append(metrics) }
eventMonitor?.request(self, didGatherMetrics: metrics)
}
/// task在请求完成前失败了(比如认证失败)调用(SessionDelegate中使用stateProvider(Session)调用)
func didFailTask(_ task: URLSessionTask, earlyWithError error: AFError) {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
self.error = error
// Task will still complete, so didCompleteTask(_:with:) will handle retry.
eventMonitor?.request(self, didFailTask: task, earlyWithError: error)
}
/// task请求完成后调用(所有task都会调用这个方法,不管成功与否)(在SessionDelegate中使用stateProvider(Session)调用)
func didCompleteTask(_ task: URLSessionTask, with error: AFError?) {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
//记录错误
self.error = self.error ?? error
validators.forEach { $0() }
eventMonitor?.request(self, didCompleteTask: task, with: error)
//重试或者完成
retryOrFinish(error: self.error)
}
/// 准备重试时调用(自己调用retryRequest时调用)
func prepareForRetry() {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
//重试次数 +1
$mutableState.write { $0.retryCount += 1 }
// 还原状态
reset()
eventMonitor?.requestIsRetrying(self)
}
/// 决定是重试还是完成(自己调用)
func retryOrFinish(error: AFError?) {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
//如果没错误或者没有代理对象, 直接调用finish()
guard let error = error, let delegate = delegate else { finish(); return }
//否则询问代理是否有重试逻辑
delegate.retryResult(for: self, dueTo: error) { retryResult in
switch retryResult {
case .doNotRetry:
//不重试, 直接finish
self.finish()
case let .doNotRetryWithError(retryError):
//不重试, 抛出错误
self.finish(error: retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
case .retry, .retryWithDelay:
//重试或者延迟重试
delegate.retryRequest(self, withDelay: retryResult.delay)
}
}
}
/// 请求完成时的操作(1. 自己调用. 2.Session deinit时对所有Request调用AFError.sessionDeinitialized, Session失效时对所有请求调用AFError.sessionInvalidated)
func finish(error: AFError? = nil) {
dispatchPrecondition(condition: .onQueue(underlyingQueue))
//如果请求已经完成了, 忽略
guard !mutableState.isFinishing else { return }
//标记为完成
mutableState.isFinishing = true
//有错误的话, 记录
if let error = error { self.error = error }
// 开始执行响应解析
processNextResponseSerializer()
//通知监听器
eventMonitor?.requestDidFinish(self)
}
/// Appends the response serialization closure to the instance.
///
/// - Note: This method will also `resume` the instance if `delegate.startImmediately` returns `true`.
///
/// - Parameter closure: The closure containing the response serialization call.
/// 线程安全地添加响应解析回调
func appendResponseSerializer(_ closure: @escaping () -> Void) {
$mutableState.write { mutableState in
//加入数组
mutableState.responseSerializers.append(closure)
//如果请求完成了,标记为继续
if mutableState.state == .finished {
mutableState.state = .resumed
}
//如果响应解析完成了, 调一下解析方法
if mutableState.responseSerializerProcessingFinished {
underlyingQueue.async { self.processNextResponseSerializer() }
}
//如果不是完成状态, 且可以转换为继续状态
if mutableState.state.canTransitionTo(.resumed) {
//问问Session是否需要立刻开始, 是的话就立刻调用resume()
underlyingQueue.async { if self.delegate?.startImmediately == true { self.resume() } }
}
}
}
/// 线程安全地获取下一个响应解析回调
func nextResponseSerializer() -> (() -> Void)? {
var responseSerializer: (() -> Void)?
$mutableState.write { mutableState in
//已经完成的解析回调个数
let responseSerializerIndex = mutableState.responseSerializerCompletions.count
//看看完成的个数是否等于存在的解析回调个数
if responseSerializerIndex < mutableState.responseSerializers.count {
responseSerializer = mutableState.responseSerializers[responseSerializerIndex]
}
}
return responseSerializer
}
/// 开始处理下一个响应解析器, 如果全部解析器都处理完了, 更新状态为finish(自己调用:1.task请求完成后会调用finish()时调用该方法, 2.添加新的解析回调之后会调用该方法, 3.解析完全部响应之后会调用)
func processNextResponseSerializer() {
guard let responseSerializer = nextResponseSerializer() else {
// 解析器处理完的话就调用全部的解析处理完成回调并删除
var completions: [() -> Void] = []
$mutableState.write { mutableState in
//先存一下完成回调数组
completions = mutableState.responseSerializerCompletions
//然后先清空解析回调数组,以及完成回调数组, 避免回调数组中调用了cancel方法, 导致循环调用
mutableState.responseSerializers.removeAll()
mutableState.responseSerializerCompletions.removeAll()
//标记为完成
if mutableState.state.canTransitionTo(.finished) {
mutableState.state = .finished
}
//标记响应解析完成
mutableState.responseSerializerProcessingFinished = true
mutableState.isFinishing = false
}
//执行完成回调
completions.forEach { $0() }
//清除请求状态
cleanup()
return
}
//如果还有响应解析回调, 调用
serializationQueue.async { responseSerializer() }
}
/// 通知Request全部的响应解析完成了
func responseSerializerDidComplete(completion: @escaping () -> Void) {
//先把完成回调加入到数组
$mutableState.write { $0.responseSerializerCompletions.append(completion) }
//然后执行下一个响应解析, 如果没有解析了就会挨个调用完成回调
processNextResponseSerializer()
}
/// 重置请求状态
func reset() {
error = nil
uploadProgress.totalUnitCount = 0
uploadProgress.completedUnitCount = 0
downloadProgress.totalUnitCount = 0
downloadProgress.completedUnitCount = 0
$mutableState.write { state in
state.isFinishing = false
state.responseSerializerCompletions = []
}
}
/// 更新上传进度
func updateUploadProgress(totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
uploadProgress.totalUnitCount = totalBytesExpectedToSend
uploadProgress.completedUnitCount = totalBytesSent
uploadProgressHandler?.queue.async { self.uploadProgressHandler?.handler(self.uploadProgress) }
}
// 线程安全的操作state属性
func withState(perform: (State) -> Void) {
$mutableState.withState(perform: perform)
}
// MARK: Task 创建时的相关方法
/// 给Request创建URLSessionTask时, Session会调用该方法取得创建的URLSessionTask, 几个子类各自实现
func task(for request: URLRequest, using session: URLSession) -> URLSessionTask {
fatalError("Subclasses must override.")
}
开放api, 可以被模块外部调用
主要为主动调用更新request请求相关方法。
更新状态:
// MARK: - 开放apis, 可以被module外部调用, 可以在任何队列调用
// MARK: 状态相关
/// 取消Request, 一旦取消了, 就再也不能继续跟挂起了
@discardableResult
public func cancel() -> Self {
$mutableState.write { mutableState in
//检测是否能取消请求
guard mutableState.state.canTransitionTo(.cancelled) else { return }
//设置状态
mutableState.state = .cancelled
//通知调用取消完成
underlyingQueue.async { self.didCancel() }
//看下最后一个task是否完成了
guard let task = mutableState.tasks.last, task.state != .completed else {
//最后一个task如果完成了, 代表请求完成, 直接走finish逻辑
underlyingQueue.async { self.finish() }
return
}
// 先恢复一下task确保请求指标被获取了
task.resume()
// 取消task
task.cancel()
//通知task取消完成
underlyingQueue.async { self.didCancelTask(task) }
}
return self
}
/// 挂起请求
@discardableResult
public func suspend() -> Self {
$mutableState.write { mutableState in
//检测是否能挂起
guard mutableState.state.canTransitionTo(.suspended) else { return }
//更新状态
mutableState.state = .suspended
//通知调用suspend()完成
underlyingQueue.async { self.didSuspend() }
//检测最后一个请求是否完成, 完成的话跳过
guard let task = mutableState.tasks.last, task.state != .completed else { return }
//挂起task
task.suspend()
//通知task挂起完成
underlyingQueue.async { self.didSuspendTask(task) }
}
return self
}
/// 继续task
@discardableResult
public func resume() -> Self {
$mutableState.write { mutableState in
//检查能否继续
guard mutableState.state.canTransitionTo(.resumed) else { return }
//更新状态
mutableState.state = .resumed
//通知调用resume()完成
underlyingQueue.async { self.didResume() }
//检测task是否全部完成
guard let task = mutableState.tasks.last, task.state != .completed else { return }
//继续task
task.resume()
//通知task继续完成
underlyingQueue.async { self.didResumeTask(task) }
}
return self
}
认证与进度api:
// MARK: - Closure API
/// http认证
@discardableResult
public func authenticate(username: String, password: String, persistence: URLCredential.Persistence = .forSession) -> Self {
let credential = URLCredential(user: username, password: password, persistence: persistence)
return authenticate(with: credential)
}
/// http认证
@discardableResult
public func authenticate(with credential: URLCredential) -> Self {
mutableState.credential = credential
return self
}
/// 设置下载进度回调以及队列, 注意只有最后设置的回调有效
@discardableResult
public func downloadProgress(queue: DispatchQueue = .main, closure: @escaping ProgressHandler) -> Self {
mutableState.downloadProgressHandler = (handler: closure, queue: queue)
return self
}
/// 设置上传进度回调以及队列, 只有最后设置的回调有效
@discardableResult
public func uploadProgress(queue: DispatchQueue = .main, closure: @escaping ProgressHandler) -> Self {
mutableState.uploadProgressHandler = (handler: closure, queue: queue)
return self
}
重定向:
// MARK: Redirects
/// 设置重定向协议对象, 只允许设置一次
@discardableResult
public func redirect(using handler: RedirectHandler) -> Self {
$mutableState.write { mutableState in
precondition(mutableState.redirectHandler == nil, "Redirect handler has already been set.")
mutableState.redirectHandler = handler
}
return self
}
缓存处理:
// MARK: Cached Responses
/// 设置缓存处理协议对象, 只允许设置一次
@discardableResult
public func cacheResponse(using handler: CachedResponseHandler) -> Self {
$mutableState.write { mutableState in
precondition(mutableState.cachedResponseHandler == nil, "Cached response handler has already been set.")
mutableState.cachedResponseHandler = handler
}
return self
}
curl相关api:
// MARK: - Lifetime APIs
/// 设置curl描述调用以及调用队列, 当urlrequest还未创建好时, 会保存最后一个设置的回调, 在urlrequest创建完成或者失败后调用, 当urlrequest已经创建完成后, 设置curl描述调用会直接调用
@discardableResult
public func cURLDescription(on queue: DispatchQueue, calling handler: @escaping (String) -> Void) -> Self {
$mutableState.write { mutableState in
if mutableState.requests.last != nil {
//已经创建了urlrequest, 直接调用
queue.async { handler(self.cURLDescription()) }
} else {
//尚未创建urlrequest, 保存回调
mutableState.cURLHandler = (queue, handler)
}
}
return self
}
/// 跟上面一个,不过是在underlyingQueue队列调用
@discardableResult
public func cURLDescription(calling handler: @escaping (String) -> Void) -> Self {
$mutableState.write { mutableState in
if mutableState.requests.last != nil {
underlyingQueue.async { handler(self.cURLDescription()) }
} else {
mutableState.cURLHandler = (underlyingQueue, handler)
}
}
return self
}
/// 设置URLRequest创建成功后的回调以及队列, 注意: 1.如果有适配器或者请求重试, 回调会被调用多次, 2.只会保存一个回调
@discardableResult
public func onURLRequestCreation(on queue: DispatchQueue = .main, perform handler: @escaping (URLRequest) -> Void) -> Self {
$mutableState.write { state in
if let request = state.requests.last {
queue.async { handler(request) }
}
state.urlRequestHandler = (queue, handler)
}
return self
}
/// 设置URLSessionTask创建完成的回调及其队列, 注意: 1.该方法不允许用来与URLSessionTask交互, 否则会影响Alamofire内部逻辑, 2.如果请求会重试, 回调可能会被调用多次
@discardableResult
public func onURLSessionTaskCreation(on queue: DispatchQueue = .main, perform handler: @escaping (URLSessionTask) -> Void) -> Self {
$mutableState.write { state in
if let task = state.tasks.last {
queue.async { handler(task) }
}
state.urlSessionTaskHandler = (queue, handler)
}
return self
}
清理内存:
// MARK: Cleanup
/// 清理内存, 子类各自实现来清理自己的数据
func cleanup() {
//父类只是通知下代理清空内存
delegate?.cleanup(after: self)
}
}
Request扩展相关:
扩展了Request实现了比较与hash操作以及文本描述
// MARK: - 扩展Request对象来实现协议
extension Request: Equatable {
//Equatable协议用uuid来比较
public static func ==(lhs: Request, rhs: Request) -> Bool {
lhs.id == rhs.id
}
}
extension Request: Hashable {
//Hashable用uuid做key
public func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
extension Request: CustomStringConvertible {
/// 对Request对象的文本描述, 包括请求方法, url, 如果已经有响应数据, 会加上响应状态码
public var description: String {
//啥都没有的话返回提示
guard let request = performedRequests.last ?? lastRequest,
let url = request.url,
let method = request.httpMethod else { return "No request created yet." }
let requestDescription = "\(method) \(url.absoluteString)"
//map函数可以对一个可选类型调用, 如果可选类型不为nil的话, 调用回调, 把内容作为参数传入
return response.map { "\(requestDescription) (\($0.statusCode))" } ?? requestDescription
//最后拼接的格式为: "请求方法 请求url 响应状态码"
}
}
// 扩展Request, 返回请求的curl格式(应该是linux环境下调试用)
extension Request {
public func cURLDescription() -> String {
guard
let request = lastRequest,
let url = request.url,
let host = url.host,
let method = request.httpMethod else { return "$ curl command could not be created" }
var components = ["$ curl -v"]
components.append("-X \(method)")
if let credentialStorage = delegate?.sessionConfiguration.urlCredentialStorage {
let protectionSpace = URLProtectionSpace(host: host,
port: url.port ?? 0,
protocol: url.scheme,
realm: host,
authenticationMethod: NSURLAuthenticationMethodHTTPBasic)
if let credentials = credentialStorage.credentials(for: protectionSpace)?.values {
for credential in credentials {
guard let user = credential.user, let password = credential.password else { continue }
components.append("-u \(user):\(password)")
}
} else {
if let credential = credential, let user = credential.user, let password = credential.password {
components.append("-u \(user):\(password)")
}
}
}
if let configuration = delegate?.sessionConfiguration, configuration.httpShouldSetCookies {
if
let cookieStorage = configuration.httpCookieStorage,
let cookies = cookieStorage.cookies(for: url), !cookies.isEmpty {
let allCookies = cookies.map { "\($0.name)=\($0.value)" }.joined(separator: ";")
components.append("-b \"\(allCookies)\"")
}
}
var headers = HTTPHeaders()
if let sessionHeaders = delegate?.sessionConfiguration.headers {
for header in sessionHeaders where header.name != "Cookie" {
headers[header.name] = header.value
}
}
for header in request.headers where header.name != "Cookie" {
headers[header.name] = header.value
}
for header in headers {
let escapedValue = header.value.replacingOccurrences(of: "\"", with: "\\\"")
components.append("-H \"\(header.name): \(escapedValue)\"")
}
if let httpBodyData = request.httpBody {
let httpBody = String(decoding: httpBodyData, as: UTF8.self)
var escapedBody = httpBody.replacingOccurrences(of: "\\\"", with: "\\\\\"")
escapedBody = escapedBody.replacingOccurrences(of: "\"", with: "\\\"")
components.append("-d \"\(escapedBody)\"")
}
components.append("\"\(url.absoluteString)\"")
return components.joined(separator: " \\\n\t")
}
}
本来这篇想写Request+四个子类的, 结果内容太多了, 四个子类下篇写……
以上完全个人学习理解, 如有错误欢迎评论指出~将第一时间修改~谢谢~