【问题标题】:Alamofire 3 Custom Encoding To Alamofire 4 Custom EncodingAlamofire 3 自定义编码到 Alamofire 4 自定义编码
【发布时间】:2017-02-22 09:06:12
【问题描述】:

我在 Alamofire 3 中使用 customParameterEncoding 编写方法。这种自定义编码只是将 queryString 中的 "[]=" 替换为 "=" 并返回它。

Alamofire.request(.GET, SearchURL, parameters: params, encoding: customEncoding, headers: headers).validate().responseJSON {
            response in
            switch response.result {
            case .success:
                print("success")
                break
            case .failure(let error):
                print("Error: " + error.localizedDescription)
                break
            }
        }

和自定义编码参数

let customEncoding =  ParameterEncoding.Custom { requestConvertible, parameters in
    let (mutableRequest, error) = ParameterEncoding.URL.encode(requestConvertible, parameters: parameters)
    mutableRequest.URL = NSURL(string: mutableRequest.URLString.stringByReplacingOccurrencesOfString("%5B%5D=", withString: "="))
    return (mutableRequest, error)
}

如何将customEncoding转换为Alamofire 4版本?

【问题讨论】:

    标签: swift swift3 alamofire


    【解决方案1】:

    在 Alamofire 4.0 中,您应该使用 ParameterEncoding

    struct CustomEncoding: ParameterEncoding {
        func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
            var request = try! URLEncoding().encode(urlRequest, with: parameters)
            let urlString = request.url?.absoluteString.replacingOccurrences(of: "%5B%5D=", with: "=")
            request.url = URL(string: urlString!)
            return request
        }
    }
    

    【讨论】:

    • 如果我使用post请求这个函数中httpBody为nil,那么如何解决编码问题。请帮我一个忙?
    【解决方案2】:

    看起来像 Alamofire 中设计的错误:https://github.com/Alamofire/Alamofire/issues/329

    这是我在 Swift3 中使用 get 和 post 方法的解决方案:

    extension NSNumber {
    fileprivate var isBool: Bool {
        return CFBooleanGetTypeID() == CFGetTypeID(self) 
      }
    }
    
    struct CustomEncoding: ParameterEncoding {
    fileprivate func escape(_ string: String) -> String {
        let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
        let subDelimitersToEncode = "!$&'()*+,;="
    
        var allowedCharacterSet = CharacterSet.urlQueryAllowed
        allowedCharacterSet.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
    
        var escaped = ""
        if #available(iOS 8.3, *) {
            escaped = string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string
        } else {
            let batchSize = 50
            var index = string.startIndex
    
            while index != string.endIndex {
                let startIndex = index
                let endIndex = string.index(index, offsetBy: batchSize, limitedBy: string.endIndex) ?? string.endIndex
                let range = startIndex..<endIndex
    
                let substring = string.substring(with: range)
    
                escaped += substring.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? substring
    
                index = endIndex
            }
        }
        return escaped
    }
    
    fileprivate func queryComponents(fromKey key: String, value: Any) -> [(String, String)] {
        var components: [(String, String)] = []
    
        if let dictionary = value as? [String: Any] {
            for (nestedKey, value) in dictionary {
                components += queryComponents(fromKey: "\(key)[\(nestedKey)]", value: value)
            }
        } else if let array = value as? [Any] {
            for value in array {
                components += queryComponents(fromKey: "\(key)[]", value: value)
            }
        } else if let value = value as? NSNumber {
            if value.isBool {
                components.append((escape(key), escape((value.boolValue ? "1" : "0"))))
            } else {
                components.append((escape(key), escape("\(value)")))
            }
        } else if let bool = value as? Bool {
            components.append((escape(key), escape((bool ? "1" : "0"))))
        } else {
            components.append((escape(key), escape("\(value)")))
        }
    
        return components
    }
    
    fileprivate 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: "&")
    }
    
    func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
        var request: URLRequest = try urlRequest.asURLRequest()
        guard let parameters = parameters else { return request }
        guard let mutableRequest = (request as NSURLRequest).mutableCopy() as? NSMutableURLRequest else {
            // Handle the error
            return request
        }
        if request.urlRequest?.httpMethod == "GET" {
            mutableRequest.url = URL(string: (mutableRequest.url?.absoluteString.replacingOccurrences(of: "%5B%5D=", with: "="))!)
        }
    
        if request.urlRequest?.httpMethod == "POST" {
            mutableRequest.httpBody = query(parameters).data(using: .utf8, allowLossyConversion: false)
            if mutableRequest.httpBody != nil {
                let httpBody = NSString(data: mutableRequest.httpBody!, encoding: String.Encoding.utf8.rawValue)!
                mutableRequest.httpBody = httpBody.replacingOccurrences(of: "%5B%5D=", with: "=").data(using: String.Encoding.utf8)
            }
        }
        request = mutableRequest as URLRequest
        return request
      }
    }
    

    然后发送请求:

    let request = Alamofire.request(URLString, method: method, parameters: parameters, encoding: CustomEncoding(), headers: headers)
                request.responseData(queue: self.netWorkQueue) { (response) in
             //......//
    }
    

    【讨论】:

      【解决方案3】:

      仅将 GET 和 POST 的结构分开也可以。

      http://matsue.github.io/post/how-to-remove-square-brackets-with-alamofire/

      Alamofire 4 与 Swift 3

      // Remove square brackets for GET request
      struct CustomGetEncoding: ParameterEncoding {
          func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
              var request = try URLEncoding().encode(urlRequest, with: parameters)
              request.url = URL(string: request.url!.absoluteString.replacingOccurrences(of: "%5B%5D=", with: "="))
              return request
          }
      }
      
      // Remove square brackets for POST request
      struct CustomPostEncoding: ParameterEncoding {
          func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
              var request = try URLEncoding().encode(urlRequest, with: parameters)
              let httpBody = NSString(data: request.httpBody!, encoding: String.Encoding.utf8.rawValue)!
              request.httpBody = httpBody.replacingOccurrences(of: "%5B%5D=", with: "=").data(using: .utf8)
              return request
          }
      }
      
      // Use structs for requests 
      Alamofire.request("http://example.com", method: .get, parameters: ["foo": ["bar1", "bar2"]], encoding: CustomGetEncoding())
      Alamofire.request("http://example.com", method: .post, parameters: ["foo": ["bar1", "bar2"]], encoding: CustomPostEncoding())
      

      【讨论】:

        【解决方案4】:

        尝试使用 URLEncoding(arrayEncoding: .noBrackets)

        Alamofire.request(.GET, SearchURL, parameters: params, encoding: URLEncoding(arrayEncoding: .noBrackets), headers: headers).validate().responseJSON {
                response in
                switch response.result {
                case .success:
                    print("success")
                    break
                case .failure(let error):
                    print("Error: " + error.localizedDescription)
                    break
                }
            }
        

        【讨论】:

        • 请添加更多详细信息以扩展您的答案,例如工作代码或文档引用。
        猜你喜欢
        • 2017-01-27
        • 1970-01-01
        • 2017-01-26
        • 2019-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多