84cfd98552b07109b590e9eae0c50cff
Alamofire(4)— 你需要知道的细节

😊😊😊Alamofire专题目录,欢迎及时反馈交流 😊😊😊


Alamofire 目录直通车 --- 和谐学习,不急不躁!


上一个篇章里面我们讲解 SessionDelegate 是事件总响应者,我们根据不同的需求 (DataTaskDelegate、DownloadTaskDelegate、UploadTaskDelegate、TaskDelegate),响应总代理然后根据需求的不同交给专业的人去做专业的事。耦合性大大降低,架构的分层更加明显! 这个篇章我要介绍 Alamofire 一些非常好用的小细节,帮助大家在日后的开发里无往不利

一、SessionDelegate的对外闭包

我们的 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 闭包
  • 这样对外提供闭包的本质:就是对外提供能力,让开发人员更加自如,方便

二、动态适配能力 - RequestAdapter

这个功能特别好用,能够提供下面两种能力。

  • 1: request 处理
  • 2: request 重定向

下面我们开始来玩玩这个适配能力

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().

五、Result

Alamofire 在请求数据会有一个 Response 但是这个不是我们最终的结果,还需要进过一层序列化。

```Swift
public func response(
queue: DispatchQueue? = nil,

top Created with Sketch.