Beim Erstellen einer GET
Anfrage gibt es keinen Textkörper für die Anfrage, sondern alles geht über die URL. Sie können auch eine URL erstellen (und den Prozentsatz, der ihr entgeht) URLComponents
.
var url = URLComponents(string: "https://www.google.com/search/")!
url.queryItems = [
URLQueryItem(name: "q", value: "War & Peace")
]
Der einzige Trick besteht darin, dass für die meisten Webdienste ein +
prozentualer Escapezeichen erforderlich ist (da dies als Leerzeichen gemäß der application/x-www-form-urlencoded
Spezifikation interpretiert wird ). Aber URLComponents
wird nicht Prozent davon entkommen. Apple behauptet, dass dies +
ein gültiges Zeichen in einer Abfrage ist und daher nicht maskiert werden sollte. Technisch gesehen sind sie richtig, dass es in einer Abfrage eines URI erlaubt ist, aber es hat eine besondere Bedeutung in application/x-www-form-urlencoded
Anfragen und sollte wirklich nicht ohne Flucht übergeben werden.
Apple räumt ein, dass wir den +
Zeichen prozentual entkommen müssen , rät jedoch, dies manuell zu tun:
var url = URLComponents(string: "https://www.wolframalpha.com/input/")!
url.queryItems = [
URLQueryItem(name: "i", value: "1+2")
]
url.percentEncodedQuery = url.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")
Dies ist eine unelegante Problemumgehung, die jedoch funktioniert. Apple empfiehlt, wenn Ihre Abfragen möglicherweise ein +
Zeichen enthalten und Sie einen Server haben, der sie als Leerzeichen interpretiert.
Wenn Sie das mit Ihrer sendRequest
Routine kombinieren , erhalten Sie so etwas wie:
func sendRequest(_ url: String, parameters: [String: String], completion: @escaping ([String: Any]?, Error?) -> Void) {
var components = URLComponents(string: url)!
components.queryItems = parameters.map { (key, value) in
URLQueryItem(name: key, value: value)
}
components.percentEncodedQuery = components.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")
let request = URLRequest(url: components.url!)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data,
let response = response as? HTTPURLResponse,
(200 ..< 300) ~= response.statusCode,
error == nil else {
completion(nil, error)
return
}
let responseObject = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any]
completion(responseObject, nil)
}
task.resume()
}
Und du würdest es so nennen:
sendRequest("someurl", parameters: ["foo": "bar"]) { responseObject, error in
guard let responseObject = responseObject, error == nil else {
print(error ?? "Unknown error")
return
}
}
Persönlich würde ich JSONDecoder
heutzutage verwenden und einen benutzerdefinierten struct
anstelle eines Wörterbuchs zurückgeben, aber das ist hier nicht wirklich relevant. Hoffentlich veranschaulicht dies die Grundidee, wie die Parameter in die URL einer GET-Anforderung prozentual codiert werden.
Siehe vorherige Überarbeitung dieser Antwort für Swift 2 und manuelle prozentuale Fluchtversuche.
extension string
mit den Werten macht? Auch wann müsste ichHttpBody
dann verwenden?