此应用程序正在从后台线程修改autolayout引擎,这可能导致引擎损坏和奇怪的崩溃

时间:2015-08-11 20:51:44

标签: iphone ios9 xcode7-beta4

当我在模拟器中运行我的应用程序时,我在控制台中获取此日志。 Haven在iOS 8中没有看到这个。我不太清楚是什么造成这种情况。有没有其他人遇到同样的问题,如果是这样,它是如何解决的?或者是否有人可以提供任何帮助?

6 个答案:

答案 0 :(得分:67)

除了主线程之外,不要更改UI。虽然它似乎可以在某些操作系统或设备上运行而不是其他操作系统,但它必然会使您的应用程序不稳定,并且无法预测崩溃。

如果您必须回复可以在后台发生的通知,请确保在主线程上发生UIKit调用

你至少有这两个选项:

异步调度

如果可以在任何线程上通知您的观察者,请使用GCD (Grand Central Dispatch)。您可以从任何线程监听并执行工作,并在dispatch_async

中封装UI更改
dispatch_async(dispatch_get_main_queue()) {
    // Do UI stuff here
}

何时使用GCD?当您不控制谁发送通知时。它可以是操作系统,Cocoapod,嵌入式库等。使用GCD每次都会随时醒来。缺点:您发现自己正在重新安排工作。

收听主线程

方便地,您可以使用queue参数指定您希望观察者通知哪个线程,在您注册时发送通知

addObserverForName:@"notification"
    object:nil
    queue:[NSOperationQueue mainQueue]
    usingBlock:^(NSNotification *note){
        // Do UI stuff here
    }

何时在主线程上观察?当您注册和注册时。当您回复通知时,您已经到了需要的位置。

主线程上的发布通知

[self performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:NO];

混合解决方案不保证仅从所述方法调用观察者。它允许更轻的观察者,成本更低的设计。这里只提到解决方案你应该避免

答案 1 :(得分:20)

Swift 3.0

use(function() {
    /*
        Business logic
    */
    return {
        name: valueName,
        list: listObject
    };
});

答案 2 :(得分:5)

您需要移动到App的MAIN线程中的所有UI部件更新。

我在背景中调用了 createMenuView(),我收到了以下错误

"此应用程序正在从后台线程修改autolayout引擎,这可能导致引擎损坏和奇怪的崩溃"

所以我将上面的方法调用到主线程中使用

$

在SWIFT 3.0和Xcode 8.0中

正确的代码如下:

    DispatchQueue.main.async {
    }

答案 3 :(得分:3)

您有从后台线程更新UI布局的代码。 更改运行代码的操作队列不需要是显式的。例如,NSURLSession.shared()在发出新请求时不使用主队列。 为了确保您的代码在主线程上运行,我使用了NSOperationQueue的静态方法mainQueue()。

夫特:

NSOperationQueue.mainQueue().addOperationWithBlock(){
    //Do UI stuff here
}

的OBJ-C:

[NSOperationQueue mainQueue] addOperationWithBlock:^{
    //Do UI stuff here
}];

答案 4 :(得分:3)

应尝试使用符号断点来检测问题: - enter image description here

符号:

[UIView layoutIfNeeded]`

条件:

!(BOOL)[NSThread isMainThread]

然后将您的UI更新代码放在主线程

DispatchQueue.main.async {}

答案 5 :(得分:0)

在我的情况下发生同样的问题,我必须以下面的方式更改代码然后它工作正常。 在ViewDidLoad中,使用main thread

调用此方法
[self performSelectorOnMainThread:@selector(setUpTableRows) withObject:nil waitUntilDone:YES];