ios - query - swift call telephone number
Solicitud GET rĂ¡pida con parĂ¡metros (7)
Al crear una solicitud
GET
, no hay cuerpo para la solicitud, sino que todo va en la URL.
Para construir una URL (y un porcentaje de escape adecuado), 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 escapado (porque interpretarán eso como un carácter de espacio según lo dictado por la
especificación
application/x-www-form-urlencoded
).
Pero los
URLComponents
no lo escaparán por ciento.
Apple afirma que
+
es un carácter válido en una consulta y, por lo tanto, no se debe escapar.
Técnicamente, son correctos, que está permitido en una consulta de un URI, pero tiene un significado especial en las
application/x-www-form-urlencoded
de
application/x-www-form-urlencoded
y realmente no debe pasarse sin escape.
Apple reconoce que tenemos que escapar porcentualmente de los caracteres
+
, 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 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 rutina
sendRequest
, 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, // is there data
let response = response as? HTTPURLResponse, // is there HTTP response
(200 ..< 300) ~= response.statusCode, // is statusCode 2XX
error == nil else { // was there no error, otherwise ...
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
}
// use `responseObject` here
}
Personalmente, usaría
JSONDecoder
hoy en día y devolvería una
struct
personalizada en lugar de un diccionario, pero eso no es realmente relevante aquí.
Esperemos que esto ilustre la idea básica de cómo codificar por ciento los parámetros en la URL de una solicitud GET.
Consulte la revisión anterior de esta respuesta para Swift 2 y las representaciones de porcentaje de escape manual.
Soy muy nuevo en swift, por lo que probablemente tenga muchos fallos en mi código, pero lo que intento lograr es enviar una solicitud
GET
a un servidor localhost con parámetros.
Más aún, estoy tratando de lograrlo dado que mi función toma dos parámetros
baseURL:string,params:NSDictionary
.
No estoy seguro de cómo combinar esos dos en la URLRequest real.
Esto es lo que he intentado hasta ahora.
func sendRequest(url:String,params:NSDictionary){
let urls: NSURL! = NSURL(string:url)
var request = NSMutableURLRequest(URL:urls)
request.HTTPMethod = "GET"
var data:NSData! = NSKeyedArchiver.archivedDataWithRootObject(params)
request.HTTPBody = data
println(request)
var session = NSURLSession.sharedSession()
var task = session.dataTaskWithRequest(request, completionHandler:loadedData)
task.resume()
}
}
func loadedData(data:NSData!,response:NSURLResponse!,err:NSError!){
if(err != nil){
println(err?.description)
}else{
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
println(jsonResult)
}
}
Esta extensión que @Rob sugirió funciona para Swift 3.0.1
No pude compilar la versión que incluyó en su publicación con Xcode 8.1 (8B62)
extension Dictionary {
/// Build string representation of HTTP parameter dictionary of keys and objects
///
/// :returns: String representation in the form of key1=value1&key2=value2 where the keys and values are percent escaped
func stringFromHttpParameters() -> String {
var parametersString = ""
for (key, value) in self {
if let key = key as? String,
let value = value as? String {
parametersString = parametersString + key + "=" + value + "&"
}
}
parametersString = parametersString.substring(to: parametersString.index(before: parametersString.endIndex))
return parametersString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!
}
}
Estoy usando esto, pruébalo en el patio de recreo. Defina las URL base como Estructura en Constantes
struct Constants {
struct APIDetails {
static let APIScheme = "https"
static let APIHost = "restcountries.eu"
static let APIPath = "/rest/v1/alpha/"
}
}
private func createURLFromParameters(parameters: [String:Any], pathparam: String?) -> URL {
var components = URLComponents()
components.scheme = Constants.APIDetails.APIScheme
components.host = Constants.APIDetails.APIHost
components.path = Constants.APIDetails.APIPath
if let paramPath = pathparam {
components.path = Constants.APIDetails.APIPath + "/(paramPath)"
}
if !parameters.isEmpty {
components.queryItems = [URLQueryItem]()
for (key, value) in parameters {
let queryItem = URLQueryItem(name: key, value: "/(value)")
components.queryItems!.append(queryItem)
}
}
return components.url!
}
let url = createURLFromParameters(parameters: ["fullText" : "true"], pathparam: "IN")
//Result url= https://restcountries.eu/rest/v1/alpha/IN?fullText=true
Puede extender su
Dictionary
para proporcionar solo
stringFromHttpParameter
si la clave y el valor se ajustan a
CustomStringConvertable
esta manera
extension Dictionary where Key : CustomStringConvertible, Value : CustomStringConvertible {
func stringFromHttpParameters() -> String {
var parametersString = ""
for (key, value) in self {
parametersString += key.description + "=" + value.description + "&"
}
return parametersString
}
}
esto es mucho más limpio y evita llamadas accidentales a
stringFromHttpParameters
en diccionarios que no tienen por qué llamar a ese método
Use NSURLComponents para construir su NSURL como este
var urlComponents = NSURLComponents(string: "https://www.google.de/maps/")!
urlComponents.queryItems = [
NSURLQueryItem(name: "q", value: String(51.500833)+","+String(-0.141944)),
NSURLQueryItem(name: "z", value: String(6))
]
urlComponents.URL // returns https://www.google.de/maps/?q=51.500833,-0.141944&z=6
fuente: https://www.ralfebert.de/snippets/ios/encoding-nsurl-get-parameters/
Yo suelo:
let dictionary = ["method":"login_user",
"cel":mobile.text!
"password":password.text!] as Dictionary<String,String>
for (key, value) in dictionary {
data=data+"&"+key+"="+value
}
request.HTTPBody = data.dataUsingEncoding(NSUTF8StringEncoding);
Swift 3 :
extension URL {
func getQueryItemValueForKey(key: String) -> String? {
guard let components = NSURLComponents(url: self, resolvingAgainstBaseURL: false) else {
return nil
}
guard let queryItems = components.queryItems else { return nil }
return queryItems.filter {
$0.name.lowercased() == key.lowercased()
}.first?.value
}
}
Lo usé para obtener el nombre de la imagen para
UIImagePickerController
en
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
:
var originalFilename = ""
if let url = info[UIImagePickerControllerReferenceURL] as? URL, let imageIdentifier = url.getQueryItemValueForKey(key: "id") {
originalFilename = imageIdentifier + ".png"
print("file name : /(originalFilename)")
}