how to throw errors in a closure in swift?

六月ゝ 毕业季﹏ 提交于 2019-12-19 09:27:38

问题


Please look at the following code:

override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {

   let deleteAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Delete", handler: {
        (action : UITableViewRowAction, indexPath : NSIndexPath)  -> Void  in

        if let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext{
            let restaurantToDelete = self.fetchResultController.objectAtIndexPath(indexPath) as! Restaurant
            managedObjectContext.deleteObject(restaurantToDelete)

            // Saving managedObjectContext instance, and catch errors if it fails
            do {
                try managedObjectContext.save()
            } catch let error as NSError {
                print("Error: \(error.localizedDescription)")
            }

        }

    })
    return deleteAction
}

the error message from Xcode is : Invalid conversion from throwing function of type '(UITableViewRowAction, NSIndexPath) throws -> Void' to non-throwing function type '(UITableViewRowAction, NSIndexPath) -> Void'

I know the problem is managedObjectContext.save() will throw errors and this is not allowed in the completion handler. I found some blog articles where they modified the closure parameters in order to make the error handling in a closure workable. While here the definition of the function is given by apple, so how can i fix this issue? Thanks a lot! :D


回答1:


the compiler is adding throws to the signature of your block because your catch clause is not exhaustive: the pattern match let error as NSError can fail... see the documentation

the signature of the closure argument is (UITableViewRowAction, NSIndexPath) -> Void, however the compiler is inferring the type of the closure that you are providing to be (UITableViewRowAction, NSIndexPath) throws -> Void

by adding another catch clause (with no pattern) after the one you already have the compiler will see that you are catching the exception locally and it will no longer infer that the signature of the closure you are providing includes throws:

do {
  try managedObjectContext.save()
} catch let error as NSError {
  print("Error: \(error.localizedDescription)")
} catch {}



回答2:


Not possible, because the closure can be invoked at any time, probably not at execution time of your function, so where should the error propagate to?

You have to call out to another function which can handle the error:

func handleError(error: ErrorType) {
    switch error {
        ...
    }
}

and then call this function with your caught error inside the closure



来源:https://stackoverflow.com/questions/31599615/how-to-throw-errors-in-a-closure-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!