获取“此应用程序正在修改后台线程的自动布局引擎”错误?

使用swift在我的OS X中遇到过这个错误:

“这个应用程序正在从后台线程修改自动布局引擎,这可能会导致引擎崩溃和奇怪的崩溃,这将在未来的版本中引发exception。

我有一个我的NSWindow ,我换窗口的contentView视图。 当我尝试在窗口上执行一个NSApp.beginSheet ,或者当我将一个subview添加到窗口时,出现错误。 试图禁用自动调整的东西,我没有任何使用自动布局。 有什么想法吗?

有时候很好,没有任何反应,其他时候它完全打破了我的UI ,什么也没有加载

好的 – find答案。 它需要放置在一个不同的线程中,只要线程函数的执行完成,就允许UI更新:

Swift 3

  DispatchQueue.main.async { // Update UI } 

Swift Version <3

 dispatch_async(dispatch_get_main_queue(){ // code here }) 

Objective-C版本

 dispatch_async(dispatch_get_main_queue(), ^{ // code here }); 

我不断地收到类似的消息/错误,同时debugging一些打印语句,而不使用“dispatch_async”

所以当你得到这个错误信息的时候就用它了

  dispatch_async(dispatch_get_main_queue()){ //code } 

Swift 3和Swift 4:

 DispatchQueue.main.async(){ //code } 

使用@markussvensson答案来检测我的问题,发现它使用这个符号断点

  1. 符号: [UIView layoutIfNeeded][UIView updateConstraintsIfNeeded]
  2. 条件: !(BOOL)[NSThread isMainThread]

在这里输入图像描述

当您尝试更新文本字段值或在后台线程中添加子视图时,可以得到此问题。 出于这个原因,你应该把这种代码放在主线程中。

您需要使用dispatch_asynch来调用调用UI更新的方法来获取主队列。 例如:

 dispatch_async(dispatch_get_main_queue(), { () -> Void in self.friendLabel.text = "You are following \(friendCount) accounts" }) 

编辑 – SWIFT 3:

现在,我们可以按照下面的代码来做:

 // Move to a background thread to do some long running work DispatchQueue.global(qos: .userInitiated).async { // Do long running task here // Bounce back to the main thread to update the UI DispatchQueue.main.async { self.friendLabel.text = "You are following \(friendCount) accounts" } } 

当我调用一个在NSURLConnectionasynchronous请求完成处理程序中进行了UI更新的块时,自从更新到iOS 9 SDK后,我遇到了这个问题。 使用dispatch_main_queue将块调用放在dispatch_async中解决了这个问题。

它在iOS 8中运行正常。

对于我来说,这个错误信息来自Admob SDK的横幅广告。

我可以通过设置一个条件断点来将原点追踪到“WebThread”。

有条件的断点来查找谁正在从后台线程更新ui

然后我可以通过封装Banner创build来摆脱这个问题:

 dispatch_async(dispatch_get_main_queue(), ^{ _bannerForTableFooter = [[GADBannerView alloc] initWithAdSize:kGADAdSizeSmartBannerPortrait]; ... } 

我不知道为什么这有帮助,因为我看不到这个代码是如何从非主线程调用的。

希望它可以帮助任何人。

有相同的问题,因为我使用performSelectorInBackground

你不能改变主界面旁边的用户界面! UIKit不是线程安全的,所以如果你这样做,上面的问题和其他一些奇怪的问题就会出现。 该应用程序甚至可以崩溃。

因此,要执行UIKit操作,您需要定义块并让它在主队列上执行:例如,

 NSOperationQueue.mainQueue().addOperationWithBlock { } 

您已经从@Mark获得了正确的代码答案,但只是为了分享我的发现:问题在于您正在请求更改视图并假设它会立即发生。 实际上,视图的加载取决于可用的资源。 如果一切都加载得很快,没有延迟,那么你什么也没有注意到。 在场景中,由于进程线程繁忙等原因,有任何延迟的情况下,应用程序运行的情况下,它应该显示的东西,即使它还没有准备好。 因此,build议将这些请求分派到asynchronous队列中,以便在负载的基础上执行。

我在重载UITableView中的数据时遇到了这个问题。 简单地调度重新加载如下解决了我的问题。

  dispatch_async(dispatch_get_main_queue(), { () -> Void in self.tableView.reloadData() }) 

很明显,你正在做一些在后台线程的UI更新。 不能预测到底在哪里,没有看到你的代码。

这些是可能发生的一些情况:

你可能会在后台线程上做些什么,而不是使用。 在相同的function,这个代码更容易被发现。

 DispatchQueue.main.async { // do UI update here } 

调用一个func做后台线程的web请求调用和它的完成处理程序调用其他func做ui更新。 解决这个尝试检查代码,你在webrequest调用后更新了UI。

 // Do something on background thread DispatchQueue.global(qos: .userInitiated).async { // update UI on main thread DispatchQueue.main.async { // Updating whole table view self.myTableview.reloadData() } } 

我在使用TouchID的时候遇到了这个问题,如果有帮助的话,包装你的成功逻辑可能会对主队列中的用户界面产生影响。

我有同样的问题。 原来我使用的是需要主队列的UIAlerts 。 但是,他们已经被弃用了
当我将UIAlerts更改为UIAlertController ,我不再有问题,也不必使用任何dispatch_async代码。 教训 – 注意警告。 他们甚至在你不期望的时候也能提供帮助。

这可能与设置文本字段/标签值或在后台线程中添加子视图一样简单,这可能会导致字段布局更改。 确保你在界面上做的任何事情只发生在主线程中。

检查这个链接: https : //forums.developer.apple.com/thread/7399

在同一个ViewController中更新UILabel中的错误消息时,我遇到了同样的问题(在正常编码的情况下尝试更新数据需要一点时间)。 我在Swift 3 Xcode 8中使用DispatchQueue ,它的工作原理。