😊😊😊Alamofire专题目录,欢迎及时反馈交流 😊😊😊api
Alamofire 目录直通车 --- 和谐学习,不急不躁!安全
上一个篇章里面咱们讲解
SessionDelegate
是事件总响应者,咱们根据不一样的需求(DataTaskDelegate、DownloadTaskDelegate、UploadTaskDelegate、TaskDelegate)
,响应总代理而后根据需求的不一样交给专业的人去作专业的事。耦合性大大下降,架构的分层更加明显! 这个篇章我要介绍Alamofire
一些很是好用的小细节,帮助你们在往后的开发里无往不利markdown
咱们的 SessionDelegate
不光是代理的总称,同时也是咱们对外逻辑强力输出口,针对咱们的代理响应提供了很是之多的闭包~😬网络
// 接受到挑战回调 open var sessionDidReceiveChallengeWithCompletion: ((URLSession, URLAuthenticationChallenge, @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void)? // 后台事件完成的回调闭包 open var sessionDidFinishEventsForBackgroundURLSession: ((URLSession) -> Void)? // 任务完成的闭包 open var taskDidComplete: ((URLSession, URLSessionTask, Error?) -> Void)? // 下载读写的进度闭包 open var downloadTaskDidWriteData: ((URLSession, URLSessionDownloadTask, Int64, Int64, Int64) -> Void)? // 接收到事件任务数据的闭包 open var dataTaskDidReceiveData: ((URLSession, URLSessionDataTask, Data) -> Void)? // 接收到响应的闭包 open var dataTaskDidReceiveResponse: ((URLSession, URLSessionDataTask, URLResponse) -> URLSession.ResponseDisposition)? 复制代码
// 建立request SessionManager.default.request(urlStr) // 监放任务回调完成状态 SessionManager.default.delegate.taskDidComplete = { (session,task,error) in print("任务完成了") } // 背后的逻辑 open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { /// Executed after it is determined that the request is not going to be retried let completeTask: (URLSession, URLSessionTask, Error?) -> Void = { [weak self] session, task, error in guard let strongSelf = self else { return } // 回调完成闭包 strongSelf.taskDidComplete?(session, task, error) } // 其余逻辑省略。。。 } 复制代码
SessionManager.default.delegate
直接对 taskDidComplete
的闭包声明SessionDelegate
的代理响应里面执行 taskDidComplete
闭包这个功能特别好用,可以提供下面两种能力。session
下面咱们开始来玩玩这个适配能力闭包
class LGAdapter: RequestAdapter{ func adapt(_ urlRequest: URLRequest) throws -> URLRequest { // token // 1: request 处理 // 2: request 重定向 var request = urlRequest request.setValue("lgcoociToken", forHTTPHeaderField: "lgtoken") let newUrlRequest = URLRequest.init(url: URL(string: "http://www.douban.com/j/app/radio/channels")!) return newUrlRequest } } 复制代码
RequestAdapter
协议的 adapt
方法urlRequest
进行处理,好比统一配置 token
urlRequest
重定向,换一个新的 request
请求.SessionManager.default.adapter = LGAdapter()
咱们请求网络习惯性 响应状态码200多
就是正确,其实咱们能够根据本身公司的特性自定义处理验证操做,更加符合实际开发架构
SessionManager.default.request(urlStr, method: .get, parameters: ["username":"Kody","password":"888888"]) .response { (response) in debugPrint(response) }.validate { (request, response, data) -> Request.ValidationResult in guard let _ = data else{ return .failure(NSError.init(domain: "lgcooci", code: 10089, userInfo: nil)) } let code = response.statusCode if code == 404 { return .failure(NSError.init(domain: "lgcooci", code: 100800, userInfo: nil)) } return .success } 复制代码
validate
方法数据data
我就返回 10089
错误状态码 == 404
的时候,咱们返回 100800
错误Alamofire
的灵活if let retrier = retrier, let error = error { retrier.should(sessionManager, retry: request, with: error) { [weak self] shouldRetry, timeDelay in guard shouldRetry else { completeTask(session, task, error) ; return } DispatchQueue.utility.after(timeDelay) { [weak self] in guard let strongSelf = self else { return } let retrySucceeded = strongSelf.sessionManager?.retry(request) ?? false if retrySucceeded, let task = request.task { strongSelf[task] = request return } else { completeTask(session, task, error) } } } } 复制代码
SessionDelegate
完成请求的时候,判断重试闭包是否存在,还有注意必定是错误的状况,没有错误没有必要重连。这里也透露出 retrier
搭配 validate
更美哦retrier
也是继承协议的处理方式,操做参考 adapter
extension LGAdapter: RequestRetrier{ func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) { print("manager = \(manager)") print("request = \(request)") print("error = \(error)") completion(true,1) // 必定要有出口,否则持续递归就会发生很严重的影响 completion(false,0) } } 复制代码
RequestRetrier
协议的 should
SessionManager.default.retrier = LGAdapter()
.Alamofire
在请求数据会有一个 Response
可是这个不是咱们最终的结果,还须要进过一层序列化。app
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 ) } return self } 复制代码
result
是通过了 responseSerializer.serializeResponse
序列化处理的结果result
的结果最终传入到了 dataResponse
public enum Result<Value> { case success(Value) case failure(Error) // 提供成功还有失败的校验 public var isSuccess: Bool {... } public var isFailure: Bool {...} public var value: Value? {...} public var error: Error? {... } } 复制代码
Swift
枚举很是强大 🤙🤙🤙,这个地方也得以体现CustomStringConvertible
和 CustomDebugStringConvertible
协议 :extension Result: CustomStringConvertible { public var description: String { // 就是返回 "SUCCESS" 和 "FAILURE" 的标识 } } extension Result: CustomDebugStringConvertible { public var debugDescription: String { // 返回标识的同时,还返回了具体内容 } } 复制代码
强大的Alamofire
👍👍👍为了方便咱们的开发还给咱们提供了 Timeline 时间轴
, 你们能够经过 Timeline
快速获得这个请求的时间数据,从而判断请求是否合理,是否须要优化....dom
timeline: Timeline: { "Request Start Time": 588099247.070, "Initial Response Time": 588099272.474, "Request Completed Time": 588099272.475, "Serialization Completed Time": 588099272.475, "Latency": 25.404 secs, "Request Duration": 25.405 secs, "Serialization Duration": 0.000 secs, "Total Duration": 25.405 secs } 复制代码
Alamofire
设计了一个队列self.queue = { let operationQueue = OperationQueue() operationQueue.maxConcurrentOperationCount = 1 operationQueue.isSuspended = true operationQueue.qualityOfService = .utility return operationQueue }() 复制代码
operationQueue.isSuspended = true
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { // 省略无关代码,方便阅读 // 请求完成,队列resume queue.isSuspended = false } 复制代码
resume
1:请求开始时间post
open func resume() { if startTime == nil { startTime = CFAbsoluteTimeGetCurrent() } } 复制代码
2:添加请求完成时间记录
init(session: URLSession, requestTask: RequestTask, error: Error? = nil) { self.session = session // 省略无关代码,方便阅读 delegate.queue.addOperation { self.endTime = CFAbsoluteTimeGetCurrent() } } 复制代码
3:初始化响应时间
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) { if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() } } 复制代码
4:时间轴设置
var timeline: Timeline { let requestStartTime = self.startTime ?? CFAbsoluteTimeGetCurrent() let requestCompletedTime = self.endTime ?? CFAbsoluteTimeGetCurrent() let initialResponseTime = self.delegate.initialResponseTime ?? requestCompletedTime return Timeline( requestStartTime: requestStartTime, initialResponseTime: initialResponseTime, requestCompletedTime: requestCompletedTime, serializationCompletedTime: CFAbsoluteTimeGetCurrent() ) } 复制代码
5:初始化记录时间以及计算时间
public init( requestStartTime: CFAbsoluteTime = 0.0, initialResponseTime: CFAbsoluteTime = 0.0, requestCompletedTime: CFAbsoluteTime = 0.0, serializationCompletedTime: CFAbsoluteTime = 0.0) { self.requestStartTime = requestStartTime self.initialResponseTime = initialResponseTime self.requestCompletedTime = requestCompletedTime self.serializationCompletedTime = serializationCompletedTime self.latency = initialResponseTime - requestStartTime self.requestDuration = requestCompletedTime - requestStartTime self.serializationDuration = serializationCompletedTime - requestCompletedTime self.totalDuration = serializationCompletedTime - requestStartTime } 复制代码
endTime
startTime
, initialResponseTime
就是在相关代理里面设置的!Timeline
的其余时间就是经过已知的 initialResponseTime
和 requestStartTime
、requestCompletedTime
、serializationCompletedTime
计算得出!这个篇章就先写到这里吧!一不当心又是
01:40
! 虽然这个点发出去,也不会有几我的看了🙁🙁🙁。可是我但愿支持个人小伙伴👬,睡一觉醒来天然而然就能接受到来自 Cooci 给你文章推送通知!一切的一切又是那么的美好😸😸😸,今夜睡去,期待好梦以后的奋斗,加油~~~~~~💪💪💪就问此时此刻还有谁?45度仰望天空,该死!我这无处安放的魅力!