以下是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開發(fā)中誊涯,UI操作都必須放在主線程中進行,如果在后臺線程更新UI會導致一些不可預知的錯誤矛缨。在實際開發(fā)中拐叉,難免會把一些UI操作放在了后臺線程中毫深,比如網絡請求回來后處理等等,在iOS 13之前的系統(tǒng)中貌似并不會導致崩潰驾诈,知識控制臺有l(wèi)og警告缠诅,但在iOS 13中某些操作就會導致文章開頭的崩潰。這堆棧信息讓人無從下手乍迄。
我把我自己解決問題的方式放在這里跟大家做個分享:
- 網絡請求回調在子線程中更新UI:
這個如果是基于AFNetWorking基本都不會出現問題管引,因為AFNetWorking會把回調結果拋回到主線程,如果是自己實現的NSURLSession那么就要注意了就乓,一定要把更新UI的操作拋回主線程汉匙,比如tableView,collectionView 的reloadData生蚁,按鈕的隱藏等等噩翠。 - 項目中用到第三方庫需要注意
第三方庫的代理回調上層時要注意是主線程還是后臺線程,特別是需要根據回調來改變UI的時候邦投。一定要確保是在主線程伤锚。我遇到的問題就是第三方回調是后臺線程,結果在里面進行了collectionView的reloadData操作導致應用crash掉志衣。 - 自己在把UI更新的代碼寫在了后臺線程中屯援。
- 一些系統(tǒng)的UI方法,比如進行網絡請求時讓狀態(tài)欄顯示小菊花動畫[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]念脯,就應該放到主線程中進行狞洋。我們項目里ASIHTTPRequest就是在后臺線程中調用了setNetworkActivityIndicatorVisible方法。AFNetWorking則不存在這個問題绿店。
總結:一定要避免在后臺線程中更新UI吉懊,遇到后臺線程就要考慮是否需要更新界面UI,如果需要就要拋回主線程里假勿。
水平有限借嗽,哪里有寫的不對的地方,大家多多交流转培,一起進步恶导。