swift - 无法使用带有完成处理程序的函数进行抛出

标签 swift asynchronous error-handling swift2 try-catch

我正在尝试使用完成处理程序将 throws 添加到我现有的函数中,但我不断收到一条警告,提示 no calls throws functions occur within try expression。在我抛出错误的部分,我收到一条错误消息

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

enum LoginError: ErrorType {
    case Invalid_Credentials
    case Unable_To_Access_Login
    case User_Not_Found
}

@IBAction func loginPressed(sender: AnyObject) {

    do{
        try self.login3(dict, completion: { (result) -> Void in

            if (result == true)
            {
                self.performSegueWithIdentifier("loginSegue", sender: nil)
            }
        })
    }
    catch LoginError.User_Not_Found
    {
        //deal with it
    }
    catch LoginError.Unable_To_Access_Login
    {
        //deal with it
    }
    catch LoginError.Invalid_Credentials
    {
        //deal with it
    }
    catch
    {
        print("i dunno")
    }

}

func login3(params:[String: String], completion: (result:Bool) throws -> Void)
{
    //Request set up
    let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
        do {
            let json = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves) as? NSDictionary
            if let parseJSON = json
            {
                let userID = parseJSON["user_id"] as? Int
                let loginError = parseJSON["user_not_found"] as? String
                let validationError = parseJSON["invalid_credentials"] as? String
                let exception = parseJSON["unable_to_access_login"] as? String

                var responseArray = [(parseJSON["user_id"] as? Int)]
                if userID != nil
                {
                    dispatch_async(dispatch_get_main_queue()) {
                        completion(result:true)
                    }

                }
                else if loginError != ""
                {
                    dispatch_async(dispatch_get_main_queue()){
                        completion(result: false)
                        self.loginErrorLabel.text = loginError
                        throw LoginError.User_Not_Found
                    }
                }
                else if validationError != ""
                {
                    dispatch_async(dispatch_get_main_queue()){
                        completion(result:false)
                        self.validationErrorLabel.text = validationError
                        throw LoginError.Invalid_Credentials
                    }

                }
                else if exception != nil
                {
                    dispatch_async(dispatch_get_main_queue()){
                        completion(result:false)
                        self.exceptionErrorLabel.text = "Unable to login"
                        throw LoginError.Unable_To_Access_Login
                    }
                }
            }
            else
            {
            }
        }
        catch let parseError {
            // Log the error thrown by `JSONObjectWithData`
        })

        task.resume()

}

最佳答案

你可以做的是将错误封装到一个可抛出的闭包中,就像下面的代码一样,以实现你想要的:

func login3(params:[String: String], completion: (inner: () throws -> Bool) -> ()) {

   let task = session.dataTaskWithRequest(request, completionHandler: { data, response, error -> Void in

            let json = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves) as? NSDictionary

            if let parseJSON = json {
               let userID = parseJSON["user_id"] as? Int
               let loginError = parseJSON["user_not_found"] as? String
               let validationError = parseJSON["invalid_credentials"] as? String
               let exception = parseJSON["unable_to_access_login"] as? String

               var responseArray = [(parseJSON["user_id"] as? Int)]
               if userID != nil {
                 dispatch_async(dispatch_get_main_queue()) {
                     completion(inner: { return true })
                 }

            }
            else if loginError != ""
            {
                dispatch_async(dispatch_get_main_queue()) {
                    self.loginErrorLabel.text = loginError
                    completion(inner: { throw LoginError.User_Not_Found })
                }
            }
            else if validationError != ""
            {
                dispatch_async(dispatch_get_main_queue()) {
                    self.validationErrorLabel.text = validationError
                    completion(inner: {throw LoginError.Invalid_Credentials})
                }
            }
            else if exception != nil
            {
                dispatch_async(dispatch_get_main_queue()){
                    self.exceptionErrorLabel.text = "Unable to login"
                    completion(inner: {throw LoginError.Unable_To_Access_Login})
                }
            }
        }
        else
        {
        }
    }

   task.resume()
}

您可以通过以下方式调用它:

self.login3(dict) { (inner: () throws -> Bool) -> Void in
   do {
     let result = try inner()
     self.performSegueWithIdentifier("loginSegue", sender: nil)
   } catch let error {
      print(error)
   }
}

诀窍在于 login3 函数采用了一个名为 'inner' 的附加闭包,类型为 () throws -> Bool。这个闭包要么提供计算结果,要么抛出异常。闭包本身是在计算过程中通过以下两种方式之一构建的:

  • 如果出现错误:inner: {throw error}
  • 如果成功:inner: {return result}

我强烈向您推荐一篇关于在异步调用中使用 try/catch 的优秀文章 Using try / catch in Swift with asynchronous closures

希望对你有帮助

关于swift - 无法使用带有完成处理程序的函数进行抛出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33402348/

相关文章:

swift - 为什么我得到一个 Thread 1 : EXC_BAD_ACCESS (code = EXC_I386_GPFLT)

javascript - 在 Selenium WebDriver 中使用 execute_async_script

javascript - 如何将异步方法拆分成更小的部分并依次调用它们?

c# - 在 c# 5.0 中, "async/await"函数是否总是在运行开始时在主线程上运行

python - 如何解决TypeError : unsupported operand type(s) for +: 'float' and 'tuple'

php - 如何在 PHP 中获取有用的错误消息?

ios - 后退按钮项替换为 "Back"

ios - Sprite 套件设置最小值。和最大。跳跃

ios - 在 Swift 中从 AppDelegate 调用自定义委托(delegate)

error-handling - 我用: "defer-panic-recover" or checking "if err != nil {//dosomething}" in golang?哪个比较好