http - data - swift alamofire example
Manejo de errores HTTP POST en Swift 2 (2)
Soy nuevo aquí, y esta es mi primera pregunta ... Intento escribir una aplicación en Swift 2 que realiza una solicitud HTTP POST pero no puedo averiguar cómo usar el nuevo manejo de errores de Swift 2. ¿Puede alguien hacerlo? Dígame, por favor, ¿cómo implementar el manejo de errores " hacer-intentar-capturar " de Swift 2 en el fragmento de código a continuación? (Este fragmento de código utiliza el antiguo manejo de errores de swift 1.2)
func post(params : Dictionary<String, String>, url : String) {
var request = NSMutableURLRequest(URL: NSURL(string: url)!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil/*, error: &err*/)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
print("Response: /(response)")
var strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Body: /(strData)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data!, options: .MutableLeaves/*, error: &err*/) as? NSDictionary
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
print(err!.localizedDescription)
let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Error could not parse JSON: ''/(jsonStr)''")
}
else {
// The JSONObjectWithData constructor didn''t return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON = json {
// Okay, the parsedJSON is here, let''s get the value for ''success'' out of it
var success = parseJSON["success"] as? Int
print("Succes: /(success)")
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn''t running?
let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Error could not parse JSON: /(jsonStr)")
}
}
})
task!.resume()
}
En general, si una función throws
, debe escribirla dentro de un bloque do catch
o simplemente marcar la función de alcance externo (en este caso, post
) como throws
:
func post(params : Dictionary<String, String>, url : String) {
let request = NSMutableURLRequest(URL: NSURL(string: url)!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
do {
request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: .PrettyPrinted)
} catch {
//handle error. Probably return or mark function as throws
print(error)
return
}
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
// handle error
guard error == nil else { return }
print("Response: /(response)")
let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Body: /(strData)")
let json: NSDictionary?
do {
json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableLeaves) as? NSDictionary
} catch let dataError {
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
print(dataError)
let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Error could not parse JSON: ''/(jsonStr)''")
// return or throw?
return
}
// The JSONObjectWithData constructor didn''t return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON = json {
// Okay, the parsedJSON is here, let''s get the value for ''success'' out of it
let success = parseJSON["success"] as? Int
print("Succes: /(success)")
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn''t running?
let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Error could not parse JSON: /(jsonStr)")
}
})
task!.resume()
}
Si no quiere manejar estos errores directamente en su función de post
, simplemente puede declararlos como throws
de los que no tiene que usar do catch
en absoluto.
Es probable que desee ajustar sus llamadas de NSJSONSerialization
en la lógica de do
/ try
/ catch
como se muestra a continuación.
En Swift 3:
var request = URLRequest(url: URL(string: urlString)!)
let session = URLSession.shared
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.httpBody = try! JSONSerialization.data(withJSONObject: parameters)
// or if you think the conversion might actually fail (which is unlikely if you built `parameters` yourself)
//
// do {
// request.httpBody = try JSONSerialization.data(withJSONObject: parameters)
// } catch {
// print(error)
// }
let task = session.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print("error: /(error)")
return
}
// this, on the other hand, can quite easily fail if there''s a server error, so you definitely
// want to wrap this in `do`-`try`-`catch`:
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
let success = json["success"] as? Int // Okay, the `json` is here, let''s get the value for ''success'' out of it
print("Success: /(success)")
} else {
let jsonStr = String(data: data, encoding: .utf8) // No error thrown, but not dictionary
print("Error could not parse JSON: /(jsonStr)")
}
} catch let parseError {
print(parseError) // Log the error thrown by `JSONObjectWithData`
let jsonStr = String(data: data, encoding: .utf8)
print("Error could not parse JSON: ''/(jsonStr)''")
}
}
task.resume()
O, en Swift 2
let request = NSMutableURLRequest(URL: NSURL(string: urlString)!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(parameters, options: [])
// or if you think the conversion might actually fail (which is unlikely if you built `parameters` yourself)
//
// do {
// request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: [])
// } catch {
// print(error)
// }
let task = session.dataTaskWithRequest(request) { data, response, error in
guard let data = data where error == nil else {
print("error: /(error)")
return
}
// this, on the other hand, can quite easily fail if there''s a server error, so you definitely
// want to wrap this in `do`-`try`-`catch`:
do {
if let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? NSDictionary {
let success = json["success"] as? Int // Okay, the `json` is here, let''s get the value for ''success'' out of it
print("Success: /(success)")
} else {
let jsonStr = String(data: data, encoding: NSUTF8StringEncoding) // No error thrown, but not NSDictionary
print("Error could not parse JSON: /(jsonStr)")
}
} catch let parseError {
print(parseError) // Log the error thrown by `JSONObjectWithData`
let jsonStr = String(data: data, encoding: NSUTF8StringEncoding)
print("Error could not parse JSON: ''/(jsonStr)''")
}
}
task.resume()
También sugiero que sea un poco más cuidadoso con el desenvolvimiento forzado de data
, porque desea detectar / manejar los errores, no bloquearse. Por ejemplo, arriba uso una declaración de guard
para desenvolverla.