从主线程访问布局引擎后,不得在后台线程中进行布局引擎的修改。

12

将现有的UIViewController转换为自动布局后,我遇到了这个崩溃,但我无法弄清楚是什么原因导致的。我搜索了dispatch_async(dispatch_get_global_queue(...))调用,但没有改变布局。

堆栈跟踪也没有提供太多帮助:

* thread #18: tid = 0x73617, 0x0000000183aa8524 libobjc.A.dylib`objc_exception_throw, stop reason = breakpoint 3.1
  * frame #0: 0x0000000183aa8524 libobjc.A.dylib`objc_exception_throw
    frame #1: 0x0000000185071100 CoreFoundation`+[NSException raise:format:] + 116
    frame #2: 0x0000000185c83894 Foundation`_AssertAutolayoutOnAllowedThreadsOnly + 192
    frame #3: 0x0000000185c835d4 Foundation`-[NSISEngine _optimizeWithoutRebuilding] + 76
    frame #4: 0x0000000185aceddc Foundation`-[NSISEngine optimize] + 112
    frame #5: 0x0000000185c82270 Foundation`-[NSISEngine performPendingChangeNotifications] + 112
    frame #6: 0x000000018af23e18 UIKit`-[UIView(Hierarchy) layoutSubviews] + 220
    frame #7: 0x000000018b15fff8 UIKit`-[UISlider layoutSubviews] + 192
    frame #8: 0x000000018af23a80 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1196
    frame #9: 0x00000001883d19d8 QuartzCore`-[CALayer layoutSublayers] + 148
    frame #10: 0x00000001883c64cc QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 292
    frame #11: 0x00000001883c638c QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 32
    frame #12: 0x00000001883433e0 QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 252
    frame #13: 0x000000018836aa68 QuartzCore`CA::Transaction::commit() + 512
    frame #14: 0x000000018836af34 QuartzCore`CA::Transaction::release_thread(void*) + 660
    frame #15: 0x0000000184103fbc libsystem_pthread.dylib`_pthread_tsd_cleanup + 572
    frame #16: 0x0000000184103ce4 libsystem_pthread.dylib`_pthread_exit + 200
    frame #17: 0x0000000184103378 libsystem_pthread.dylib`_pthread_wqthread + 1504
    frame #18: 0x0000000184102d8c libsystem_pthread.dylib`start_wqthread + 4
(lldb)

有没有办法找出导致布局触发的确切位置?


如果您的主线程冲突或任何其他进程正在中断主线程,请在grand dispatch中调用您的方法。dispatch_after(time, dispatch_get_main_queue(), {}) - Anbu.Karthik
你可以在后台线程中制作一些动画。 - Sergey
@Sergey,我认为这不是问题,因为如果是这种情况,在自动布局之前它们也不会工作。 - Iulian Onofrei
2个回答

13

UI上的任何更改都应在主线程上进行。另一个重要的问题是:您可以在后台线程中从视图创建对象!!!但是,为了在视图上显示或对其进行其他更改,只应在主线程上工作,而这个问题是发生此问题的主要原因。

最后,为了解决这个问题,您可以轻松使用'DispatchQueue'。

DispatchQueue.main.async {
  // do your work
}

12

在仔细查看异常跟踪信息后,我终于找到了问题。问题在于我在后台线程更改了一个UISlider实例的value属性。

但是没有地方说明必须在主线程上更改它!(感谢Apple)显然,UISlider实现了value的setter并强制执行布局或类似操作。


7
谢谢 - 从错误消息中并不明显,这可能是问题所在 - 在阅读了您的回复后,我发现我正在后台线程上打开模态对话框 - 这在iOS 12中没有问题,但在iOS 13中导致了我的应用程序崩溃。 - Nostradamus
3
谢谢,@Nostradamus。我刚刚将我的代码添加到了主线程,并且它起作用了。dispatch_async(dispatch_get_main_queue(), ^{ // Code });奇怪的是它只会在IOS 13中崩溃,而不会在IOS 12中。 - Mihir Oza
@MacMark,是的,现在看来很明显,但我觉得2017年时出于某种原因我没有意识到。 - Iulian Onofrei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接