这个应用程序正在从后台线程修改自动布局引擎。错误呢?

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

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

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

有时它很好,什么都没有发生,其他时候它完全打破了我的UI,什么都没有加载

158709 次浏览

它需要放在一个不同的线程中,允许UI在线程函数执行完成后立即更新:

现代迅速:

DispatchQueue.main.async {
// Update UI
}

旧版本的Swift,在Swift 3之前。

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

objective - c:

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

有同样的问题,因为我正在使用performSelectorInBackground

当我在一个NSURLConnection异步请求完成处理程序中调用一个做UI更新的块时,我有这个问题,因为更新到iOS 9 SDK。使用dispatch_main_queue将块调用放在dispatch_async中解决了这个问题。

它在iOS 8中运行良好。

我在使用TouchID时遇到了这个问题,如果这对其他人有帮助,包装你的成功逻辑,它可能在主队列中对UI有作用。

你在使用print语句进行调试没有使用'dispatch_async'时得到类似的错误消息 所以当你得到错误消息时,就该使用

斯威夫特4

DispatchQueue.main.async { //code }

斯威夫特3

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

早期的Swift版本

dispatch_async(dispatch_get_main_queue()){ //code }

当您尝试更新文本字段值或在后台线程中添加子视图时,可能会遇到此问题。因此,应该将这类代码放在主线程中。

您需要用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"
}
}
我也有同样的问题。原来我使用的是需要主队列的UIAlerts。但是,他们已经弃用.
当我将UIAlerts更改为UIAlertController时,我不再有这个问题,并且不必使用任何dispatch_async代码。教训是,注意警告。他们会在你意想不到的时候帮助你。

你不能在主线程中越位修改UI !UIKit不是线程安全的,所以如果你这样做,上面的问题和其他一些奇怪的问题会出现。应用程序甚至会崩溃。

所以,要做UIKit操作,你需要定义block并让它在主队列上执行:例如,

NSOperationQueue.mainQueue().addOperationWithBlock {


}

它可以像设置文本字段/标签值或在后台线程中添加子视图一样简单,这可能会导致字段的布局发生变化。确保你对接口所做的任何事情都只发生在主线程中。

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

对我来说,这个错误消息来自Admob SDK的一个横幅。

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

条件断点找到谁正在更新ui从后台线程

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

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

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

希望它能帮助到任何人。

你已经从@Mark那里得到了正确的代码答案,但是,只是分享我的发现: 问题是,你要求改变视图,并假设它会立即发生。实际上,视图的加载取决于可用资源。如果加载速度足够快,没有延迟,那么你就不会注意到任何事情。在某些场景中,由于进程线程繁忙等原因而导致延迟,应用程序会遇到这样的情况:即使还没有准备好,它也应该显示某些内容。因此,在异步队列中分派这些请求是明智的,这样它们就可以根据负载执行。< / p >

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

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

“此应用程序正在从后台线程修改自动布局引擎”错误在实际问题发生后很长时间才会记录在控制台中,因此如果不使用断点,调试这个错误可能会很困难。

我使用@markussvensson的答案来检测我的问题,并使用这个象征性的断点(调试>断点>创建符号断点)发现它:

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

enter image description here

在模拟器上构建和运行应用程序,并复制导致抛出错误消息的步骤(应用程序将比平时慢!)然后Xcode将停止应用程序并标记从后台线程访问UI的代码行(例如func的调用)。

我有同样的问题时,试图更新错误消息在UILabel在同一个ViewController(它需要一点时间来更新数据时,试图这样做的正常编码)。我在Swift 3 Xcode 8中使用了DispatchQueue,它可以工作。

显然你正在后台线程上做一些UI更新。在没有看到代码的情况下,无法准确预测位置。

以下是一些可能发生的情况:-

你可能正在后台线程上做一些事情,但没有使用。在同一个函数中,这段代码更容易被发现。

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()
}
}
对我来说,问题是这样的。 确保在主线程上执行performSegueWithIdentifier::

dispatch_async (dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier:@"ViewController" sender:nil];
});

斯威夫特4,

假设,如果您正在使用操作队列调用某个方法

operationQueue.addOperation({
self.searchFavourites()
})

假设函数searchfavorites是这样的,

func searchFavourites() {
DispatchQueue.main.async {
//Your code
}
}

如果你在主线程中调用“searchfavorites”方法中的所有代码,如果你在其中更新一些UI,它仍然会给出一个错误。

这个应用程序正在从后台修改自动布局引擎

.引擎被主线程访问后的线程

所以使用溶液,

operationQueue.addOperation({
DispatchQueue.main.async {
self.searchFavourites()
}
})

对于这种情况。

我还遇到了这个问题,当我将窗口大小调整到小于初始值时,看到输出中打印了大量这样的消息和堆栈跟踪。花了很长时间来解决这个问题,我想我应该分享一个相当简单的解决方案。我曾经在NSTextView到IB上启用了Can Draw Concurrently,这告诉AppKit它可以从另一个线程调用视图的draw(_:)方法。禁用后,我不再收到任何错误消息。在更新到macOS 10.14 Beta之前,我没有遇到任何问题,但与此同时,我也开始修改代码以使用文本视图执行工作。

如果你想追踪这个错误,使用主线程检查器暂停问题复选框。 在大多数情况下,修复它很容易,只需将有问题的行分派到主队列中即可。< / p >

enter image description here

“这个应用程序正在从后台线程修改自动布局引擎”的主要问题是,它似乎在实际问题发生后很长一段时间才被记录下来,这可能会使它很难排除故障。

我设法通过创建三个符号断点来解决这个问题。

调试>断点>创建符号断点…

断点1:

  • 象征:-[UIView setNeedsLayout]

  • 条件:!(BOOL)[NSThread isMainThread]

断点2:

  • 象征:-[UIView layoutIfNeeded]

  • 条件:!(BOOL)[NSThread isMainThread]

断点3:

  • 象征:-[UIView updateConstraintsIfNeeded]

  • 条件:!(BOOL)[NSThread isMainThread]

使用这些断点,您可以很容易地在非主线程上错误地调用UI方法的实际行中获得断点。

看看日志里的这一行

$S12AppName18ViewControllerC11Func()ySS_S2StF + 4420

你可以检查哪个函数从后台线程调用,或者你在哪里调用API方法,你需要像这样从主线程调用你的函数。

DispatchQueue.main.async { func()}

func()是你想在API调用结果中调用的函数

日志在这里

This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes.
Stack:(
0   Foundation                          0x00000001c570ce50 <redacted> + 96
1   Foundation                          0x00000001c5501868 <redacted> + 32
2   Foundation                          0x00000001c5544370 <redacted> + 540
3   Foundation                          0x00000001c5543840 <redacted> + 396
4   Foundation                          0x00000001c554358c <redacted> + 272
5   Foundation                          0x00000001c5542e10 <redacted> + 264
6   UIKitCore                           0x00000001f20d62e4 <redacted> + 488
7   UIKitCore                           0x00000001f20d67b0 <redacted> + 36
8   UIKitCore                           0x00000001f20d6eb0 <redacted> + 84
9   Foundation                          0x00000001c571d124 <redacted> + 76
10  Foundation                          0x00000001c54ff30c <redacted> + 108
11  Foundation                          0x00000001c54fe304 <redacted> + 328
12  UIKitCore                           0x00000001f151dc0c <redacted> + 156
13  UIKitCore                           0x00000001f151e0c0 <redacted> + 152
14  UIKitCore                           0x00000001f1514834 <redacted> + 868
15  UIKitCore                           0x00000001f1518760 <redacted> + 104
16  UIKitCore                           0x00000001f1543370 <redacted> + 1772
17  UIKitCore                           0x00000001f1546598 <redacted> + 120
18  UIKitCore                           0x00000001f14fc850 <redacted> + 1452
19  UIKitCore                           0x00000001f168f318 <redacted> + 196
20  UIKitCore                           0x00000001f168d330 <redacted> + 144
21  AppName                        0x0000000100b8ed00 $S12AppName18ViewControllerC11Func()ySS_S2StF + 4420
22  AppName                        0x0000000100b8d9f4 $S12CcfU0_y10Foundation4DataVSg_So13NSURLResponseCSgs5Error_pSgtcfU_ + 2384
23  App NAme                        0x0000000100a98f3c $S10Foundation4DataVSgSo13NSURLResponseCSgs5Error_pSgIegggg_So6NSDataCSgAGSo7NSErrorCSgIeyByyy_TR + 316
24  CFNetwork                           0x00000001c513aa00 <redacted> + 32
25  CFNetwork                           0x00000001c514f1a0 <redacted> + 176
26  Foundation                          0x00000001c55ed8bc <redacted> + 16
27  Foundation                          0x00000001c54f5ab8 <redacted> + 72
28  Foundation                          0x00000001c54f4f8c <redacted> + 740
29  Foundation                          0x00000001c55ef790 <redacted> + 272
30  libdispatch.dylib                   0x000000010286f824 _dispatch_call_block_and_release + 24
31  libdispatch.dylib                   0x0000000102870dc8 _dispatch_client_callout + 16
32  libdispatch.dylib                   0x00000001028741c4 _dispatch_continuation_pop + 528
33  libdispatch.dylib                   0x0000000102873604 _dispatch_async_redirect_invoke + 632
34  libdispatch.dylib                   0x00000001028821dc _dispatch_root_queue_drain + 376
35  libdispatch.dylib                   0x0000000102882bc8 _dispatch_worker_thread2 + 156
36  libsystem_pthread.dylib             0x00000001c477917c _pthread_wqthread + 472
37  libsystem_pthread.dylib             0x00000001c477bcec start_wqthread + 4
)