美文网首页
Alamofire之请求

Alamofire之请求

作者: 狂奔的胖蜗牛 | 来源:发表于2019-12-14 15:15 被阅读0次

    1 原生网络请求与Alamofire区别

    先来看看原生的网络请求是怎么样请求的:

    let session = URLSession(configuration: .default)
    let url = "https://ip.cn"
    let request = URLRequest(url: URL(string: url)!)
    let task = session.dataTask(with: request) { (data, response, error) in
        print(String(bytes: data!, encoding: .utf8)!)
    }
    task.resume()
    

    再来看看Alamofire是怎么请求的:

    Alamofire
        .request("https://ip.cn")
        .responseData { respons in
            print(String(bytes: respons.data!, encoding: .utf8)!)
        }
    

    可以看出,Alamofire要简洁很多。然而我们要知道一件事情,Alamofire在请求网络的时候,依然是调用的系统原生的URLSession和URLRequest等,只是Alamofire给我们封装好了要如何调用。

    2 揭开Alamofire.request()方法的面纱

    2.1 查看Alamofire.request()的源码

    @discardableResult  //如果不接收本方法的返回值,不会有提示
    public func request(
        _ url: URLConvertible, //请求的url,符合URLConvertible协议的实例即可
        method: HTTPMethod = .get, //请求方法,默认GET请求
        parameters: Parameters? = nil, //请求参数
        encoding: ParameterEncoding = URLEncoding.default, //参数编码方式
        headers: HTTPHeaders? = nil) //请求头
        -> DataRequest // 请求实例
    {
        return SessionManager.default.request(
            url,
            method: method,
            parameters: parameters,
            encoding: encoding,
            headers: headers
        )
    }
    

    通过源码,可以看出,request()方法内部,实际上是调用了SessionManager单例的request()方法,参数原封不动的传递了过去。

    2.2查看SessionManager.default.request()的源码

        @discardableResult
        open func request(
            _ url: URLConvertible, //请求url
            method: HTTPMethod = .get, //请求方法
            parameters: Parameters? = nil, //请求参数
            encoding: ParameterEncoding = URLEncoding.default, //参数编码方式
            headers: HTTPHeaders? = nil) //请求头
            -> DataRequest //请求实例
        {
            var originalRequest: URLRequest?
    
            do {
                // 通过传递进来的url、method、headers创建出原生的请求
                originalRequest = try URLRequest(url: url, method: method, headers: headers)
                // 通过给定的编码方式编码参数获得编码过后的请求
                let encodedURLRequest = try encoding.encode(originalRequest!, with: parameters)
                // 调用自身的request(_ urlRequest: URLRequestConvertible)方法,并返回
                return request(encodedURLRequest)
            } catch {
                return request(originalRequest, failedWith: error)
            }
        }
    

    可以看出,本方法只是把传入的参数编码,然后生成原生的请求,传递给下一个方法进行处理。本方法还没有发送出请求。

    2.3查看SessionManager.default.request(_ urlRequest: URLRequestConvertible)的源码

        @discardableResult
        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)
            }
        }
    

    通过源码,可以看出,请求是在本方法中发送出去的。

    3 Alamofire请求参数

    @discardableResult
    public func request(
        _ url: URLConvertible,
        method: HTTPMethod = .get,
        parameters: Parameters? = nil,
        encoding: ParameterEncoding = URLEncoding.default,
        headers: HTTPHeaders? = nil)
        -> DataRequest
    {
        return SessionManager.default.request(
            url,
            method: method,
            parameters: parameters,
            encoding: encoding,
            headers: headers
        )
    }
    

    本方法中,涉及到Alamofire的内容有:

    • URLConvertible
    public protocol URLConvertible {
        func asURL() throws -> URL
    }
    

    可以看到,这是一个协议,这也就是说,传入的url不一定是一个url字符串,只要是遵守了URLConvertible协议的实例就可以。Alamofire帮我们实现了很多,我们直接使用就可以了。如下:

    extension String: URLConvertible {
        public func asURL() throws -> URL {
            guard let url = URL(string: self) else { throw AFError.invalidURL(url: self) }
            return url
        }
    }
    extension URL: URLConvertible {
        public func asURL() throws -> URL { return self }
    }
    extension URLComponents: URLConvertible {
        public func asURL() throws -> URL {
            guard let url = url else { throw AFError.invalidURL(url: self) }
            return url
        }
    }
    

    所以,传入的url可以是String、URL、URLComponents三者之一。当然,我们是可以自定义的只要实现了协议即可。

    • HTTPMethod
    public enum HTTPMethod: String {
        case options = "OPTIONS"
        case get     = "GET"
        case head    = "HEAD"
        case post    = "POST"
        case put     = "PUT"
        case patch   = "PATCH"
        case delete  = "DELETE"
        case trace   = "TRACE"
        case connect = "CONNECT"
    }
    

    这个没什么好说的。请求方法列表。默认是GET请求。

    • Parameters
    public typealias Parameters = [String: Any]
    

    可以看出,参数是字典,key必须是String。默认是nil。

    • ParameterEncoding
    public protocol ParameterEncoding {
        func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest
    }
    

    参数编码方式传入的是遵循了ParameterEncoding协议,实现了编码参数方法的实例。默认值URLEncoding.default。

    • HTTPHeaders
    public typealias HTTPHeaders = [String: String]
    

    请求头也是字典,key和value都是String,默认值是nil。

    至此,Alamofire的请求流程全部走了一遍。

    4 总结

    通过上面的流程,我们可以发现,Alamofire在很多地方是可以按照自己的需求去定制的。包括但不仅限于如下内容:

    • 1.可以自定义传入url的类型
    • 2.可以自定义传入参数编码的类型,也就可以自定义参数的编码方式
    • 3.可以自定义SessionManager
    • 4.可以设置任务是否是直接发出,默认是直接发出请求
    • 5.可以自定义请求转换方式

    相关文章

      网友评论

          本文标题:Alamofire之请求

          本文链接:https://www.haomeiwen.com/subject/cfkqpftx.html