从主线程访问后,不得从后台线程执行对布局引擎的修改
Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread
我在将现有的 UIViewController
转换为自动布局后遇到此崩溃,但我无法弄清楚是什么原因造成的。我确实搜索了 dispatch_async(dispatch_get_global_queue(...))
个调用,但 none 更改了布局。
堆栈跟踪也非常无用:
* 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)
有没有办法找出触发布局的确切位置?
再次查看堆栈跟踪后,我终于发现了问题所在。问题是我正在后台线程上更改 UISlider
实例的 value
属性。
但是没有任何地方声明必须在主线程上更改它! (谢谢,Apple)显然,UISlider
似乎实现了 value
的 setter 并强制布局或类似的东西。
总是在 UI 处进行更改应该在主线程上进行。还有一个重要的主题是你可以在后台线程中从视图中创建一个对象!!!但是为了在视图中显示或对其进行其他更改应该在主线程上工作,这个主题是出现此问题的主要原因。
终于可以轻松使用 'DispatchQueue'
来解决这个问题了
DispatchQueue.main.async {
// do your work
}
我在将现有的 UIViewController
转换为自动布局后遇到此崩溃,但我无法弄清楚是什么原因造成的。我确实搜索了 dispatch_async(dispatch_get_global_queue(...))
个调用,但 none 更改了布局。
堆栈跟踪也非常无用:
* 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)
有没有办法找出触发布局的确切位置?
再次查看堆栈跟踪后,我终于发现了问题所在。问题是我正在后台线程上更改 UISlider
实例的 value
属性。
但是没有任何地方声明必须在主线程上更改它! (谢谢,Apple)显然,UISlider
似乎实现了 value
的 setter 并强制布局或类似的东西。
总是在 UI 处进行更改应该在主线程上进行。还有一个重要的主题是你可以在后台线程中从视图中创建一个对象!!!但是为了在视图中显示或对其进行其他更改应该在主线程上工作,这个主题是出现此问题的主要原因。
终于可以轻松使用 'DispatchQueue'
来解决这个问题了DispatchQueue.main.async {
// do your work
}