【问题标题】:Waiting for Callback Function to Finish : Swift等待回调函数完成:Swift
【发布时间】:2015-12-01 18:41:52
【问题描述】:

我想在用户从 LoginController 登录时更改视图。当 access = true 时,更改控制器。但是,我不能在 user.login 中执行此操作,因为它给了我一个错误,说我必须在主线程上处理它。现在我知道有解决方案,但我一直在寻找一个星期,并在圈子里跑来跑去。我已经足够接近,可以产生下面的内容了。

我想分享 3 条信息: 登录控制器:

var access = false
        user.login(
            {(response: Bool) -> () in
                access = response
                print(access)
            },username: emailField.text!, password: passwordField.text!)
        if(access){
            print("YAY")
            let controller = storyboard?.instantiateViewControllerWithIdentifier("NewsFeed") as! NewsFeed
            presentViewController(controller, animated: true, completion: nil)
        }else{
            print("NAY")
        }

登录类:

func login(completionHandler : (response: Bool) -> (), username: String, password: String){
    //Set the calback with the calback in the function parameter
    let parameters : [String: AnyObject] = ["tag": "login", "email": username, "password": password]
    manager.postDataToServer(
        {(response: NSDictionary) -> () in
            if(response["success"] as! Int == 1){
                // Log user in
            }else{
                // User not able to login

                }
                completionHandler(response: false)
            }
        }, page: "login", params: parameters)
}

API 管理器:

func postDataToServer(completionHandler: (response: NSDictionary) -> (), page: String, params: [String: AnyObject]){
    // Gets the information and returns the User
    // Works completely fine

}

回答:请下查看更新后的回答

请看@Rob 的回答。但是,您可能会收到一条错误消息,提示 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“-[UIKeyboardTaskQueue waitUntilAllTask​​sAreFinished] 只能从主线程调用。”。这是因为除非在主线程上,否则您无法更改视图。只需将其包装在

NSOperationQueue.mainQueue().addOperationWithBlock {
        //Change View
    } 

更新 我意识到我的错误是在处理信息之前我没有在我的一个字段中结束编辑。我通过执行以下操作来修复它,passwordField.endEditing 和 emailField.endEditing(为了安全起见)

【问题讨论】:

  • 顺便说一句,manager 在主线程上调用它的闭包吗?如果您使用 AFNetworking 或 Alamofire,它们通常会使用主队列,但如果是您自己编写的代码,您需要确保将这个完成处理程序分派到主队列。
  • 我不确定,我可以给您发送一封电子邮件,以便您检查我的 APIManager 代码吗?
  • 查看我的 Stack Overflow 个人资料以获取“联系我”链接。但是,没有冒犯,我宁愿不通过你的 API 代码。 :) 如果您使用的是NSURLSession,请确保执行完成处理程序的NSOperationQueue.mainQueue().addOperationWithBlock { ... }(或dispatch_async(dispatch_get_main_queue()) { ... })。
  • 哈哈,没问题。看起来我还没有实现它。到目前为止它可以工作,但我有更多使用这个 API 的调用,所以我宁愿第一次就做对。我将在互联网上搜索以寻求帮助。感谢所有帮助。

标签: swift asynchronous callback


【解决方案1】:

无需等待响应,只需将要执行的代码移动到闭包内即可:

user.login( { response in
    if response {
        print("YAY")
        let controller = self.storyboard?.instantiateViewControllerWithIdentifier("NewsFeed") as! NewsFeed
        self.presentViewController(controller, animated: true, completion: nil)
    } else {
        print("NAY")
    }
}, username: emailField.text!, password: passwordField.text!)

更好的是,我会更改这些参数的顺序,以便闭包是最后一个参数(然后您可以使用“尾随闭包”语法):

func loginWithUsername(username: String, password: String, completionHandler : (response: Bool) -> ()) {
    // your login code here
}

然后:

user.loginWithUsername(emailField.text!, password: passwordField.text!) { response in
    if response {
        print("YAY")
        let controller = self.storyboard?.instantiateViewControllerWithIdentifier("NewsFeed") as! NewsFeed
        self.presentViewController(controller, animated: true, completion: nil)
    } else {
        print("NAY")
    }
}

【讨论】:

  • 这是我最初的尝试,但这是我收到的消息:由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“-[UIKeyboardTaskQueue waitUntilAllTask​​sAreFinished] 只能从主线程调用。”
  • 这可能源于您从哪里调用它(可能来自UITextField 委托方法之一?)。告诉我们你在哪里打电话。但是,对于你的问题,添加代码等待总是错误的答案,所以让我们看看你从哪里调用它。
  • 你是对的,我用的是模拟器,键盘还在。单击登录后,我添加了“passwordField.endEditing(true)”的代码,它就像一个魅力。(无需使用 NSOperationQueue.mainQueue().addOperationWithBlock
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-11
  • 1970-01-01
  • 2016-03-09
  • 2016-02-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多