美文网首页
Alamofire源码解析 - ParameterEncodin

Alamofire源码解析 - ParameterEncodin

作者: wanglj | 来源:发表于2017-03-27 15:15 被阅读0次
    • 这段代码就是对ParameterEncoding协议的三种不同实现,分别是URLEncodingJSONEncodingPropertyListEncoding。以及定义了Parameters类型
    /// A dictionary of parameters to apply to a `URLRequest`.
    public typealias Parameters = [String: Any]
    
    /// A type used to define how a set of parameters are applied to a `URLRequest`.
    public protocol ParameterEncoding {
        /// Creates a URL request by encoding parameters and applying them onto an existing request.
        ///
        /// - parameter urlRequest: The request to have parameters applied.
        /// - parameter parameters: The parameters to apply.
        ///
        /// - throws: An `AFError.parameterEncodingFailed` error if encoding fails.
        ///
        /// - returns: The encoded request.
        func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest
    }
    
    • ParameterEncoding协议定义了一个encode方法,返回encoded request

    URLEncoding

    定义了四个静态参数,用于快速获取对应的类型。defaultmethodDependent都返回默认值

        public enum Destination {
            case methodDependent, queryString, httpBody
        }
    
        // MARK: Properties
    
        /// Returns a default `URLEncoding` instance.
        public static var `default`: URLEncoding { return URLEncoding() }
    
        /// Returns a `URLEncoding` instance with a `.methodDependent` destination.
        public static var methodDependent: URLEncoding { return URLEncoding() }
    
        /// Returns a `URLEncoding` instance with a `.queryString` destination.
        public static var queryString: URLEncoding { return URLEncoding(destination: .queryString) }
    
        /// Returns a `URLEncoding` instance with an `.httpBody` destination.
        public static var httpBody: URLEncoding { return URLEncoding(destination: .httpBody) }
    

    URLEncodingencode方法:

        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
        }
    
    
    • 检查urlRequest能否正常生成,parameters不能为空。
    • destination.queryString,或者method.get, .head, .delete类型时,如果parameter不为空把里面的键值对传化为“xx=xx&yy=yy"的格式然后赋值给URLComponents.percentEncodedQuery最后urlRequest.url = urlComponents.url。另一种情况直接把query返回的字符串赋给httpBody
    ["a":"apple","b":"book","c":["conent","capacity","contact"],
    "d":["4":"dose","5":"dairy"],"e":true,"f":12]
    应该转化成:
    "a=apple&b=book&c[]=conent&c[]=capacity
    &c[]=contact&d[4]=dose&d[5]=dairy&e=1&f=12"
    但是实际转化过程中使用了
    public func escape(_ string: String) -> String 方法
    所以最终结果是如下:
    "a=apple&b=book&c%5B%5D=conent&c%5B%5D=capacity
    &c%5B%5D=contact&d%5B4%5D=dose&d%5B5%5D=dairy&e=1&f=12"
    其中的“[”,"]"变成了“%5B”,"%5D"
    

    JSONEncoding

    JSONEncoding有两个encode方法,除了ParameterEncoding的添加了一个encode(_ urlRequest:,withJSONObject jsonObject:Any? = nil) -> URLRequest,两个方法的实现基本相似并且很简单

      public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
            var urlRequest = try urlRequest.asURLRequest()
    
            guard let parameters = parameters else { return urlRequest }
    
            do {
                let data = try JSONSerialization.data(withJSONObject: parameters, options: options)
    
                if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
                    urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
                }
    
                urlRequest.httpBody = data
            } catch {
                throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
            }
    
            return urlRequest
        }
    

    PropertyListEncoding

    很少用到

        public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
            var urlRequest = try urlRequest.asURLRequest()
    
            guard let parameters = parameters else { return urlRequest }
    
            do {
                let data = try PropertyListSerialization.data(
                    fromPropertyList: parameters,
                    format: format,
                    options: options
                )
    
                if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
                    urlRequest.setValue("application/x-plist", forHTTPHeaderField: "Content-Type")
                }
    
                urlRequest.httpBody = data
            } catch {
                throw AFError.parameterEncodingFailed(reason: .propertyListEncodingFailed(error: error))
            }
    
            return urlRequest
        }
    }
    
    
    

    相关文章

      网友评论

          本文标题:Alamofire源码解析 - ParameterEncodin

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