2015-06-24 17 views
16

Sono nuovo qui, e questa è la mia prima domanda ... Provo a scrivere un'app in Swift 2 che effettua una richiesta POST HTTP ma non riesco a capire come usa la nuova gestione degli errori di Swift 2. Qualcuno può dirmi come implementare la gestione degli errori "do-try-catch" di Swift 2 allo snippet di codice qui sotto? (Questo frammento di codice utilizza la vecchia gestione degli errori di rapida 1,2)Errore HTTP POST Gestione in Swift 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() 
} 

risposta

36

Si presume che si desideri avvolgere le chiamate NSJSONSerialization nella logica do/try/catch come illustrato di seguito.

In 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() 

Oppure, a 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() 

Vorrei anche suggerire di essere un po 'più attenti a scartare forzato di data, perché si vuole rilevare/manico gli errori, non crash. Ad esempio, sopra uso una dichiarazione guard per scartarla.

6

In generale, se una funzione throws si deve scrivere all'interno di un blocco di do catch o semplicemente marcare la funzione ambito esterno (in questo caso post) come 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() 
} 

Se non si desidera gestire questi errori a destra nella funzione post si può semplicemente dichiararlo come throws di quello che non c'è bisogno di usare do catch affatto

+0

Funziona! Grazie per questa rapida risposta –

+0

Rob, colpa mia hai ragione :) Upvote – Qbyte