Al crear una GET
solicitud, no hay cuerpo para la solicitud, sino que todo va en la URL. Para crear una URL (y el porcentaje adecuado de escape), también puede usar URLComponents
.
var url = URLComponents(string: "https://www.google.com/search/")!
url.queryItems = [
URLQueryItem(name: "q", value: "War & Peace")
]
El único truco es que la mayoría de los servicios web necesitan un +
porcentaje de caracteres de escape (porque lo interpretarán como un carácter de espacio según lo dicta la application/x-www-form-urlencoded
especificación ). Pero URLComponents
no escapará por ciento. Apple sostiene que +
es un carácter válido en una consulta y, por lo tanto, no debe escaparse. Técnicamente, tienen razón, que está permitido en una consulta de un URI, pero tiene un significado especial en las application/x-www-form-urlencoded
solicitudes y realmente no debe pasarse sin escape.
Apple reconoce que tenemos que escapar por ciento de los +
personajes, pero aconseja que lo hagamos manualmente:
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")
Esta es una solución temporal poco elegante, pero funciona, y es lo que Apple aconseja si sus consultas pueden incluir un +
carácter y tiene un servidor que las interpreta como espacios.
Entonces, combinando eso con tu sendRequest
rutina, terminas con algo como:
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()
}
Y lo llamarías así:
sendRequest("someurl", parameters: ["foo": "bar"]) { responseObject, error in
guard let responseObject = responseObject, error == nil else {
print(error ?? "Unknown error")
return
}
}
Personalmente, usaría JSONDecoder
hoy en día y devolvería struct
un diccionario personalizado en lugar de un diccionario, pero eso no es realmente relevante aquí. Con suerte, esto ilustra la idea básica de cómo codificar porcentualmente los parámetros en la URL de una solicitud GET.
Consulte la revisión anterior de esta respuesta para Swift 2 y versiones de escape de porcentaje manual.
extension string
está haciendo con los valores. Además, ¿cuándo debería usarloHttpBody
entonces?