iOS13 崩溃 Fatal Exception: NSInternalInconsistencyException

独自空忆成欢 提交于 2020-11-25 11:52:28

以下是Firebase的崩溃日志:

Fatal Exception: NSInternalInconsistencyException
Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.`
0  应用名称                           0x100df14e4 CLSProcessRecordAllThreads + 4316009700
1  应用名称                           0x100df18cc CLSProcessRecordAllThreads + 4316010700
2  应用名称                           0x100de1144 CLSHandler + 4315943236
3  应用名称                           0x100defae8 __CLSExceptionRecord_block_invoke + 4316003048
4  libdispatch.dylib              0x1c515c184 _dispatch_client_callout + 16
5  libdispatch.dylib              0x1c510ec44 _dispatch_lane_barrier_sync_invoke_and_complete + 56
6  应用名称                           0x100def554 CLSExceptionRecord + 4316001620
7  应用名称                           0x100def380 CLSExceptionRecordNSException + 4316001152
8  应用名称                           0x100deef74 CLSTerminateHandler() + 4316000116
9  libc++abi.dylib                0x1c525c304 std::__terminate(void (*)()) + 16
10 libc++abi.dylib                0x1c525bc58 __cxa_get_exception_ptr + 30
11 libc++abi.dylib                0x1c525bc18 __cxxabiv1::exception_cleanup_func(_Unwind_Reason_Code, _Unwind_Exception*) + 122
12 libobjc.A.dylib                0x1c51b71d0 _objc_exception_destructor(void*) + 354
13 Foundation                     0x1c5964d64 -[NSISEngine tryToOptimizeReturningMutuallyExclusiveConstraints] + 318
14 Foundation                     0x1c57662dc -[NSISEngine withBehaviors:performModifications:] + 32
15 UIKitCore                      0x1c984fee4 -[UIView(UIConstraintBasedLayout) _resetLayoutEngineHostConstraints] + 76
16 UIKitCore                      0x1c99271b4 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1952
17 QuartzCore                     0x1cbe135f8 -[CALayer layoutSublayers] + 284
18 QuartzCore                     0x1cbe17e28 CA::Layer::layout_if_needed(CA::Transaction*) + 480
19 QuartzCore                     0x1cbe23894 CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 136
20 QuartzCore                     0x1cbd6c9f0 CA::Context::commit_transaction(CA::Transaction*, double) + 304
21 QuartzCore                     0x1cbd96890 CA::Transaction::commit() + 676
22 QuartzCore                     0x1cbd97814 CA::Transaction::release_thread(void*) + 228
23 libsystem_pthread.dylib        0x1c51ae350 _pthread_tsd_cleanup + 580
24 libsystem_pthread.dylib        0x1c51ab248 _pthread_exit + 80
25 libsystem_pthread.dylib        0x1c51ac29c _pthread_wqthread_legacy_worker_wrap + 94
26 libsystem_pthread.dylib        0x1c51ac034 _pthread_wqthread + 420
27 libsystem_pthread.dylib        0x1c51aeae0 start_wqthread + 8

错误信息:Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread
翻译成中文的意思大概就是:绝对不能改变布局在后台线程中,必须在主线程中才能进行布局操作

大家都知道在iOS开发中,UI操作都必须放在主线程中进行,如果在后台线程更新UI会导致一些不可预知的错误。在实际开发中,难免会把一些UI操作放在了后台线程中,比如网络请求回来后处理等等,在iOS 13之前的系统中貌似并不会导致崩溃,知识控制台有log警告,但在iOS 13中某些操作就会导致文章开头的崩溃。这堆栈信息让人无从下手。

我把我自己解决问题的方式放在这里跟大家做个分享:

  1. 网络请求回调在子线程中更新UI:
    这个如果是基于AFNetWorking基本都不会出现问题,因为AFNetWorking会把回调结果抛回到主线程,如果是自己实现的NSURLSession那么就要注意了,一定要把更新UI的操作抛回主线程,比如tableView,collectionView 的reloadData,按钮的隐藏等等。
  2. 项目中用到第三方库需要注意
    第三方库的代理回调上层时要注意是主线程还是后台线程,特别是需要根据回调来改变UI的时候。一定要确保是在主线程。我遇到的问题就是第三方回调是后台线程,结果在里面进行了collectionView的reloadData操作导致应用crash掉。
  3. 自己在把UI更新的代码写在了后台线程中。
  4. 一些系统的UI方法,比如进行网络请求时让状态栏显示小菊花动画[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES],就应该放到主线程中进行。我们项目里ASIHTTPRequest就是在后台线程中调用了setNetworkActivityIndicatorVisible方法。AFNetWorking则不存在这个问题。

总结:一定要避免在后台线程中更新UI,遇到后台线程就要考虑是否需要更新界面UI,如果需要就要抛回主线程里。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!