Invalid conversion with do-try-catch in a block

Given the following code:


managedObjectContext.performBlock({ () -> Void in
                    do
                    {
                        try managedObjectContext.save()
                        print("Success")
                      
                    } catch let error as NSError
                    {
                        print("fail")
                    }
                })


I am receiving the following error:

`invalid conversion from throwing function of type '() throws -> Void' to non-throwing function type '() -> Void'`.


Any advice on how to resolve it?

Adding a catch-all "catch" will let things compile:

moc.performBlock {
    do {
        try moc.save()
        print("Success")
    } catch let error as NSError {
        print("Fail: \(error.localizedDescription)")
    } catch {
        print("Fail: \(error)")
    }
}

If you're not using the NSError, you may as well use just a single, generic "catch".


If you don't catch all possible errors, the "throws" propagates to the caller, in this case, "performBlock". However, "performBlock" doesn't expect an error, so you must catch all possible errors, or you must call "try!", unsafely, instead.


The error isn't super friendly, so it may be worth filing a bug report to make it easier to understand.

So then how do you throw an error out ? I dont want to catch the error always sometimes the caller should catch it.

If you're using

performBlock(_:)
, then the block that's passed in is executed asynchronously. It's therefore not a good idea to throw an error from within that block, which is possibly executed on a different thread, the thread of the managed object context. It's still possible to catch any errors, but it's not a good idea—and not possible as far as I know—to throw an error from within that block.


If you do want to throw an error, then it's better to use

performBlockAndWait(_:)
. This will perform the block synchronously, which allows you to catch any errors and, if necessary, thrown any errors yourself. Make sure to throw any errors outside the block that you pass to
performBlockAndWait(_:)
. Take a look at the below example to see how this could be done.


var fetchRequestError: NSError?
var results = [NSManagedObject]()


managedObjectContext.performBlockAndWait({ () -> Void in
    do {
        try results = managedObjectContext.executeFetchRequest(fetchRequest) as! [NSManagedObject]
    } catch {
        fetchRequestError = error as NSError
    }
})


if fetchRequestError != nil {
    throw CoreDataError.FetchRequestDidFail
}


I've just started transitioning to Swift 2 myself so this is new to me. Feel free to make any suggestions to improve the way errors are handled in the above example. Keep in mind that

performBlockAndWait(_:)
blocks the current thread, which may not be what you want, especially if you're performing a fetch request.
Invalid conversion with do-try-catch in a block
 
 
Q