Alamofire 3 Custom Encoding To Alamofire 4 Custom Encoding

后端 未结 3 1774
天命终不由人
天命终不由人 2021-02-15 23:16

I have method writing in Alamofire 3 with customParameterEncoding. This custom encoding just replaces \"[]=\" with \"=\" in queryString and returns it.

Alamofire         


        
相关标签:
3条回答
  • 2021-02-15 23:47

    In Alamofire 4.0 you should use 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
        }
    }
    
    0 讨论(0)
  • 2021-02-15 23:47

    Just separating structs for GET and POST also works.

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

    Alamofire 4 with 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())
    
    0 讨论(0)
  • 2021-02-16 00:00

    Looks like a bug by design in Alamofire: https://github.com/Alamofire/Alamofire/issues/329

    This is my solution in Swift3 with both get & post method:

    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
      }
    }
    

    then send request:

    let request = Alamofire.request(URLString, method: method, parameters: parameters, encoding: CustomEncoding(), headers: headers)
                request.responseData(queue: self.netWorkQueue) { (response) in
             //......//
    }
    
    0 讨论(0)
提交回复
热议问题