Generell @rmaddy ist richtig in seinem Kommentar. Aber wir können diese Codierung als eine lustige Übung abschalten.
Wir müssen dafür einen benutzerdefinierten Encoder verwenden. Alamofire unterstützt jeden benutzerdefinierten Encoder, der das ParameterEncoding
Protokoll anstelle von encoding: .URL
implementiert.
So habe ein wenig Kopie & eingefügt Code von den ursprünglichen Alamofire Codebasis verwenden kann, und erstellen Sie eigenen Encoder
public struct NOURLEncoding: ParameterEncoding {
//protocol implementation
public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
var urlRequest = try urlRequest.asURLRequest()
guard let parameters = parameters else { return urlRequest }
if HTTPMethod(rawValue: urlRequest.httpMethod ?? "GET") != nil {
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
}
}
return urlRequest
}
//append query parameters
private 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: "&")
}
//Alamofire logic for query components handling
public 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
}
//escaping function where we can select symbols which we want to escape
//(I just removed + for example)
public 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 = ""
escaped = string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string
return escaped
}
}
extension NSNumber {
fileprivate var isBool: Bool { return CFBooleanGetTypeID() == CFGetTypeID(self) }
}
I Idee nicht, warum es sinnvoll sein kann. Aber benutzerdefinierte Codierung kann einfach hinzugefügt werden. Jetzt können Sie nur Alamofire Anfrage mit unserem neuen Encoder
Alamofire.request("http://www.mysite/v1/search", method: .get, parameters: ["N": "4249847587+1798040122"], encoding: NOURLEncoding())
https://github.com/Alamofire/Alamofire/pull/167/commits/570ed7e8fee36106c93a3251fbb1a97d818e7f09 – Sahil
Nein, Sie möchten, dass das '+' als '% 2B' codiert wird. Andernfalls behandelt der Server das '+' als Codierung eines Leerzeichen. – rmaddy
Danke, Leute, ich habe das Problem gelöst. Du hast mir sehr geholfen –