2016-10-13 14 views
2

私は、Alamofire 3でcustomParameterEncodingを使ってメソッドを記述しています。このカスタムエンコーディングは、queryStringの "[] ="を "="に置き換えて返します。 4バージョンをAlamofireするcustomEncodingを変換する方法Alamofire 3カスタムエンコーディングTo Alamofire 4カスタムエンコーディング

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

答えて

5

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

と私はPOSTリクエストを使用している場合httpBodyは、符号化の問題を解決するためにどのようにして、この機能ではnilです。ちょっとお願いがあるんですが –

0

はAlamofireの設計によるバグのように見える:リクエストを送信し、その後

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 
     //......// 
} 
https://github.com/Alamofire/Alamofire/issues/329

これは& postメソッドを取得し、両方とSwift3の私のソリューションです。

7

GETとPOSTの構造体を分離するだけでも動作します。

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

Alamofire 4スウィフト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()) 
関連する問題