Swift编程iOS 进阶开发Alamofire

Alamofire - Request

2019-08-20  本文已影响136人  Cooci_和谐学习_不急不躁

上一篇 Alamofire-后台下载 其中就介绍了关于 SesssionManagerSessionDelegate的分层!下面我在总结一下,然后开始一个 Alamofire 非常重要的模块 Request!

一、SesssionManager的总结

总结:SesssionManager负责创建和管理 Request 对象及其底层NSURLSession

首先给大家贴出一张非常熟悉的图,看懂了这张图对下面理解 Request 的帮助大大的

二、Request

1. Request参数编码

public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
    var urlRequest = try urlRequest.asURLRequest()

    guard let parameters = parameters else { return urlRequest }

    if let method = HTTPMethod(rawValue: urlRequest.httpMethod ?? "GET"), encodesParametersInURL(with: method) {
        guard let url = urlRequest.url else {
            throw AFError.parameterEncodingFailed(reason: .missingURL)
        }

        if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty {
            let percentEncodedQuery = (urlComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters)
            urlComponents.percentEncodedQuery = percentEncodedQuery
            urlRequest.url = urlComponents.url
        }
    } else {
        if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
            urlRequest.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
        }
        urlRequest.httpBody = query(parameters).data(using: .utf8, allowLossyConversion: false)
    }
    return urlRequest
}
private func query(_ parameters: [String: Any]) -> String {
    var components: [(String, String)] = []

    for key in parameters.keys.sorted(by: <) {
        let value = parameters[key]!
        components += queryComponents(fromKey: key, value: value)
    }
    return components.map { "\($0)=\($1)" }.joined(separator: "&")
}

普通方法就直接拼接到URL的后面,例如POST方法就是把这些编码好的参数对放入请求体中。其中还要加入Content-Type的请求头

2. Request内部关系梳理

探索完 request 繁琐事务之一的参数编码之后,开始分析内部:url -> request -> task 的过程。这个过程中还建立 task以及request 之间的绑定关系

open func request(_ urlRequest: URLRequestConvertible) -> DataRequest {
    var originalRequest: URLRequest?
    do {
        originalRequest = try urlRequest.asURLRequest()
        let originalTask = DataRequest.Requestable(urlRequest: originalRequest!)
        let task = try originalTask.task(session: session, adapter: adapter, queue: queue)
        let request = DataRequest(session: session, requestTask: .data(originalTask, task))

        delegate[task] = request
        if startRequestsImmediately { request.resume() }

        return request
    } catch {
        return request(originalRequest, failedWith: error)
    }
}

可能很多小伙伴这个时候就会有疑虑,你不就是通过SessionDelegate实现代理, 为什么这里还要有一个 DataTaskDelegate

open func urlSession(
    _ session: URLSession,
    downloadTask: URLSessionDownloadTask,
    didFinishDownloadingTo location: URL)
{
  // 省略属性闭包回调的情况
    if let delegate = self[downloadTask]?.delegate as? DownloadTaskDelegate {
        delegate.urlSession(session, downloadTask: downloadTask, didFinishDownloadingTo: location)
    }
}
func urlSession(
    _ session: URLSession,
    downloadTask: URLSessionDownloadTask,
    didFinishDownloadingTo location: URL)
{
    temporaryURL = location

    guard
        let destination = destination,
        let response = downloadTask.response as? HTTPURLResponse
    else { return }

    let result = destination(location, response)
    let destinationURL = result.destinationURL
    let options = result.options

    self.destinationURL = destinationURL

    do {
        if options.contains(.removePreviousFile), FileManager.default.fileExists(atPath: destinationURL.path) {
            try FileManager.default.removeItem(at: destinationURL)
        }

        if options.contains(.createIntermediateDirectories) {
            let directory = destinationURL.deletingLastPathComponent()
            try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
        }
        try FileManager.default.moveItem(at: location, to: destinationURL)
    } catch {
        self.error = error
    }
}

我们从 SessionManager -> Request 这一过程明面上就是直接交付,但是背地都是通过代理响应联通的:SessionDelegate -> 具体的Request的delegate。看到这里,是不是感觉非常的爽!优秀的框架总是能够给你在思想方面带来很大的提升,我们平时开发的时候也会有很恶心的耦合度,通讯问题。那么想必 Alamofire 的设计思路肯定能够给你带来一定的启示!

就问此时此刻还有谁?45度仰望天空,该死!我这无处安放的魅力!

上一篇下一篇

猜你喜欢

热点阅读