xcode在宁静的回调中呈现segue(swift)

时间:2015-10-13 22:07:07

标签: ios iphone swift xcode6 segue

我是自学Swift用户并试图做一些简单的事情,但它让我很难过。我有一个简单的登记表。在提交注册项目后,我想通过segue将页面移动到“如何工作”页面,但仅当我的restful API返回成功时。这是我到目前为止所拥有的;随时给我一个更好的方法来做这件事。所有的批评都是受欢迎的。

df = sns.load_dataset("df")
g = sns.FacetGrid(df)
g.map(s.skdeplot, "df.columns");

我有一个名为let myUrl = NSURL(string:"http://www.example.com/scripts/Register.php") let request = NSMutableURLRequest(URL: myUrl!) request.HTTPMethod = "POST" let postString = "email=\(email)&password=\(pass)" request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding) let task = NSURLSession.sharedSession().dataTaskWithRequest(request){ data, response, error in if (error != nil) { println("Error: \(error)") return } var err: NSError? var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &err) as? NSDictionary var showTutorial : Bool = false if let parseJSON = json { var returnValue = parseJSON["status"] as? String println("Status: \(returnValue)") var isUserRegistered: Bool = false if (returnValue == "Success") { showTutorial = true } else if (returnValue == "Error") { // handle error } } // if successful registration, show how it works page if (showTutorial) { self.performSegueWithIdentifier("howItWorksSegue", sender: self) } } task.resume() 的segue附加到此视图控制器,转到howItWorksSegue。我从Xcode收到此错误:

  

2015-10-12 21:22:43.261 ZiftDine [11396:2307755]断言失败 - [UIKeyboardTaskQueue waitUntilAllTask​​sAreFinished],/ SourceCache / UIKit_Sim / UIKit-3347.44.2 / Keyboard / UIKeyboardTaskQueue.m:374   2015-10-12 21:22:43.391 ZiftDine [11396:2307755]由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:' - [UIKeyboardTaskQueue waitUntilAllTask​​sAreFinished]只能从主线程中调用。'

3 个答案:

答案 0 :(得分:7)

使用UI完成的任何操作都应该在主线程上完成,尝试将performSegue调用包装成这样:

dispatch_async(dispatch_get_main_queue(),{
    self.performSegueWithIdentifier("howItWorksSegue", sender: self)
})

答案 1 :(得分:1)

@ Swinny89为您的问题提供了解决方案,但有些解释是有条理的。

如果您阅读了dataTaskWithRequest:completionHandler:的描述,这是您正在使用的方法(尽管您的Swift代码使用尾随闭包语法删除completionHandler标签并将闭包放在括号之外)它说:

  

completionHandler:加载时调用的完成处理程序   请求已完成。此处理程序在委托队列上执行。

然后,如果你阅读了init方法sessionWithConfiguration:delegate:delegateQueue:的描述,那就说:

  

queue:用于调度委托调用和完成的队列   处理程序。如果为nil,则会话为其创建一个串行操作队列   执行所有委托方法调用和完成处理程序调用。

串行操作队列在不同的线程上运行。

因此,将所有这些信息放在一起,就意味着你的完成闭包将在主线程以外的线程上执行。

iOS / Mac开发的基本规则是您必须从主线程执行所有UI调用。如果一个呼叫改变了屏幕上的任何内容,那就是一个UI呼叫。

您的代码正在从后台线程调用performSegueWithIdentifier:。它会更改屏幕上显示的内容,因此必须是UI调用。因此,它需要在主线程上运行。

队列为dispatch_async()的GCD函数dispatch_get_main_queue()提交一个在主调度队列上运行的闭包,一个在主线程上运行的队列。

所以Swinny的解决方案可以解决您的问题。

这里的外卖:

每当你在一个闭包中运行代码时,请停下来思考:“我是否肯定这个闭包将始终在主线程上运行?”如果答案是否定的,请将代码包含在dispatch_async(dispatch_get_main_queue()的调用中,就像Swinny的回答一样。

答案 2 :(得分:0)

@Duncan C和@ Swinny89的答案都很好。对于任何从谷歌进来的人来说,Swift 3中的语法有所改变:

DispatchQueue.main.async(execute: {
    self.performSegueWithIdentifier("howItWorksSegue", sender: self)
})