Search code examples
iosswiftswift2xcode7-beta5

Swift 2 try/catch


I've started converting one of my projects to Swift 2 and I ran into this issue. To start this block below is perfectly valid try/catch, in fact it was generated by the Xcode migration tool.

do {
       requestData = try NSJSONSerialization.dataWithJSONObject(requestContents, options: [])
} catch var error as NSError {
      requestError = error
      requestData = nil
}

If I use that same code inside a closure, such as a dataTaskWithRequest I get an error. The error is at the task assignment, but its the catch that causes it. The following also works but I'm not capturing the error.

let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, taskError) -> Void in
    if taskError != nil {
        NSLog("Error making request: " + taskError!.localizedDescription)
    } 
    else {
        do {
            let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableLeaves) as? NSDictionary
            if let parseJSON = json as NSDictionary? {
                // do some parsing here
            }
        } 
        catch {
           NSLog("Error in JSON serialization")
     }
  }
})
task.resume()

but if I try to capture the error with:

} catch let e as NSError {

I get this error:

Invalid conversion from throwing function of type '(_, _, _) throws -> Void' to non-throwing function type '(NSData?, NSURLResponse?, NSError?) -> Void'

I did discover that:

} catch _ {

works but a lot of good that does me.

Am I missing something or should I be filing a bug?

(This is Xcode 7b5)


Solution

  • The completion handler of dataTaskWithRequest is not designed to throw error like JSONObjectWithData of NSJSONSerialization, whose signature is:

    class func JSONObjectWithData(data: NSData, options opt: NSJSONReadingOptions) throws -> AnyObject
    

    Doing the following would work (same as what you have tried):

    catch _
    

    But that won't give us any detail about the error from the one that throws, namely, from class func JSONObjectWithData.

    As a result, we need a way to consume the non-throwable dataTaskWithRequest while preserving the one that throws - JSONObjectWithData.

    I have tried the following:

    catch let error as NSError
    {
         //error specific to JSON serialization
         NSLog("Error in JSON serialization \(error)")
    }
    catch
    {
         //exhaust the error
         NSLog("Some error")
    }