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

Mar*_*ark 298 macos background-thread autolayout swift

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

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

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

有时它很好,没有任何反应,有时它完全打破了我的UI负担

Mar*_*ark 628

好的 - 找到了答案.它需要放在一个不同的线程中,允许UI在线程函数执行完成后立即更新:

斯威夫特3

 DispatchQueue.main.async {
    // Update UI
 }
Run Code Online (Sandbox Code Playgroud)

Swift版本<3

dispatch_async(dispatch_get_main_queue(){
    // code here
})
Run Code Online (Sandbox Code Playgroud)

Objective-C版本

dispatch_async(dispatch_get_main_queue(), ^{
    // code here
});
Run Code Online (Sandbox Code Playgroud)

  • 虽然没有伤害,但^(void)而不仅仅是^是没有必要的.Objective-C版本的答案很好. (4认同)
  • 为了在Objective C中工作,将^(void)放在{在代码块中,然后是分号后面. (3认同)
  • 这对我来说可以.对于我的问题是,做一个网络请求,并在内部成功完成块我调用函数来更新UI.由于UIKit不是线程安全的,需要调度回主线程来更新UI. (2认同)

Nai*_*hta 145

使用print语句调试时得到类似的错误消息,而不使用'dispatch_async'所以当你收到错误消息时,它的使用时间

斯威夫特4

DispatchQueue.main.async { //code }
Run Code Online (Sandbox Code Playgroud)

斯威夫特3

DispatchQueue.main.async(){ //code }
Run Code Online (Sandbox Code Playgroud)

早期的Swift版本

dispatch_async(dispatch_get_main_queue()){ //code }
Run Code Online (Sandbox Code Playgroud)

  • 因为语法是错误的,应该是:`dispatch_async(dispatch_get_main_queue()^ {/*UI相关的代码*/});`编辑:我更新了他的答案,语法格式的作品更好. (5认同)

k06*_*06a 76

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

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

在此输入图像描述

  • 嗯 我赞成这一点,因为这似乎很有意义。但是,执行没有中断,并且我的日志中仍然出现错误。我还可以使用其他条件来设置符号断点吗? (3认同)
  • 从Xcode 9开始,它是一个内置功能。只需确保在“方案”设置的“诊断”选项卡中启用了“主线程检查器”选项 (2认同)

Jor*_*nez 25

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

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

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

编辑 - 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"
   }
}
Run Code Online (Sandbox Code Playgroud)


mar*_*son 21

对我来说,此错误消息源自Admob SDK中的横幅.

我能够通过设置条件断点来跟踪原点到"WebThread".

条件断点,以查找谁从后台线程更新ui

然后我通过封装Banner创建来解决这个问题:

dispatch_async(dispatch_get_main_queue(), ^{
   _bannerForTableFooter = [[GADBannerView alloc] initWithAdSize:kGADAdSizeSmartBannerPortrait];
   ...
}
Run Code Online (Sandbox Code Playgroud)

我不知道为什么这有帮助,因为我无法看到如何从非主线程调用此代码.

希望它可以帮助任何人.


spo*_*uck 20

自从我调用在NSURLConnection异步请求完成处理程序中执行UI更新的块后更新到iOS 9 SDK,我遇到了这个问题.使用dispatch_main_queue将块调用放入dispatch_async解决了该问题.

它在iOS 8中运行良好.


Bob*_*bby 10

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


www*_*.se 8

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

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

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

断点 1:

  • 象征: -[UIView setNeedsLayout]

  • 健康)状况: !(BOOL)[NSThread isMainThread]

断点 2:

  • 象征: -[UIView layoutIfNeeded]

  • 健康)状况: !(BOOL)[NSThread isMainThread]

断点 3:

  • 象征: -[UIView updateConstraintsIfNeeded]

  • 健康)状况: !(BOOL)[NSThread isMainThread]

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


Cho*_*war 7

你不能改变主线程越位的UI!UIKit不是线程安全的,所以如果你这样做,就会出现上述问题以及其他一些奇怪的问题.该应用程序甚至可以崩溃.

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

NSOperationQueue.mainQueue().addOperationWithBlock {

}
Run Code Online (Sandbox Code Playgroud)


Ash*_*sey 7

显然你在后台线程上做了一些UI更新.无法预测代码,无法准确预测位置.

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

你可能在后台线程上做了一些事情而没有使用.在相同的功能中,这个代码更容易被发现.

DispatchQueue.main.async { // do UI update here }
Run Code Online (Sandbox Code Playgroud)

调用func在后台线程上执行web请求调用,并调用其他函数执行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()
            }
}
Run Code Online (Sandbox Code Playgroud)