iOS 14使用UIImagePicker拍照频繁崩溃求助
关于iOS 14上CameraUI
CAMPriorityNotificationCenter 崩溃的排查与修复 我之前碰到过类似的崩溃场景,结合你提供的崩溃日志来看,这个问题的核心是快速枚举期间修改了集合(从栈里的__NSFastEnumerationMutationHandler就能明确这一点)——系统在CAMPriorityNotificationCenter内部遍历通知条目时,集合被意外修改了,导致抛出异常。iOS13只是偶发,iOS14上报频率上升,大概率是因为iOS14对Scene生命周期和CameraUI内部通知流程的处理逻辑有调整,让原本的潜在冲突更容易触发。
下面是我总结的排查方向和修复建议:
排查重点
- 崩溃触发时机:从日志里的
-[UIApplication _deactivateForReason:notify:]可以看出,崩溃发生在App进入后台(场景失活)的阶段。 - 核心冲突点:系统在发送通知的同步流程中,我们的代码修改了
CAMPriorityNotificationCenter的观察者集合(比如添加/移除通知监听者)。
具体修复方案
调整Scene生命周期回调中的操作时机
如果你在sceneDidEnterBackground、applicationDidEnterBackground这类回调里,有做Camera相关的通知监听移除、或者Camera会话资源清理的操作,把这些操作改成主线程异步执行。比如:- (void)sceneDidEnterBackground:(UIScene *)scene { dispatch_async(dispatch_get_main_queue(), ^{ // 这里做Camera相关的观察者移除、资源清理 [[NSNotificationCenter defaultCenter] removeObserver:self name:someCameraNotification object:nil]; }); }这样可以避免在系统同步处理通知的流程中,直接修改观察者集合导致冲突。
避免在通知回调中同步修改观察者
如果你注册了Camera相关的通知(比如相机权限变化、会话状态通知),不要在通知的回调方法里同步移除当前观察者或者修改其他会影响通知集合的状态。可以改用延迟执行的方式:- (void)cameraStatusChanged:(NSNotification *)note { // 不要在这里直接removeObserver:self [self performSelector:@selector(removeCameraObserver) withObject:nil afterDelay:0]; } - (void)removeCameraObserver { [[NSNotificationCenter defaultCenter] removeObserver:self name:someCameraNotification object:nil]; }检查第三方相机相关框架
如果你用了第三方的相机SDK,也有可能是SDK内部在处理生命周期时的逻辑和iOS14的新机制冲突了。可以尝试更新SDK到最新版本,或者联系SDK开发者确认是否有已知的iOS14适配问题。
格式化后的崩溃日志
Last Exception Backtrace (0) #0 (null) in __exceptionPreprocess () #1 (null) in objc_exception_throw () #2 (null) in __NSFastEnumerationMutationHandler () #3 (null) in -[CAMPriorityNotificationCenter _postNotification:forEntries:] () #4 (null) in -[CAMPriorityNotificationCenter _notificationReceiver:] () #5 (null) in __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ () #6 (null) in ___CFXRegistrationPost_block_invoke () #7 (null) in _CFXRegistrationPost () #8 (null) in _CFXNotificationPost () #9 (null) in -[NSNotificationCenter postNotificationName:object:userInfo:] () #10 (null) in -[UIApplication _deactivateForReason:notify:] () #11 (null) in __101-[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:]_block_invoke_2 () #12 (null) in _UIScenePerformActionsWithLifecycleActionMask () #13 (null) in __101-[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:]_block_invoke () #14 (null) in -[_UISceneLifecycleMultiplexer _performBlock:withApplicationOfDeactivationReasons:fromReasons:] () #15 (null) in -[_UISceneLifecycleMultiplexer _evalTransitionToSettings:fromSettings:forceExit:withTransitionStore:] () #16 (null) in -[_UISceneLifecycleMultiplexer uiScene:transitionedFromState:withTransitionContext:] () #17 (null) in __186-[_UIWindowSceneFBSSceneTransitionContextDrivenLifecycleSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:]_block... () #18 (null) in +[BSAnimationSettings(UIKit) tryAnimatingWithSettings:actions:completion:] () #19 (null) in _UISceneSettingsDiffActionPerformChangesWithTransitionContext () #20 (null) in -[_UIWindowSceneFBSSceneTransitionContextDrivenLifecycleSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:] () #21 (null) in __64-[UIScene scene:didUpdateWithDiff:transitionContext:completion:]_block_invoke () #22 (null) in -[UIScene _emitSceneSettingsUpdateResponseForCompletion:afterSceneUpdateWork:] () #23 (null) in -[UIScene scene:didUpdateWithDiff:transitionContext:completion:] () #24 (null) in -[UIApplicationSceneClientAgent scene:handleEvent:withCompletion:] () #25 (null) in -[FBSScene updater:didUpdateSettings:withDiff:transitionContext:completion:] () #26 (null) in __94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke_2 () #27 (null) in -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] () #28 (null) in __94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke () #29 (null) in _dispatch_client_callout () #30 (null) in _dispatch_block_invoke_direct$VARIANT$armv81 () #31 (null) in __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ () #32 (null) in -[FBSSerialQueue _targetQueue_performNextIfPossible] () #33 (null) in -[FBSSerialQueue _performNextFromRunLoopSource] () #34 (null) in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ () #35 (null) in __CFRunLoopDoSource0 () #36 (null) in __CFRunLoopDoSources0 () #37 (null) in __CFRunLoopRun () #38 (null) in CFRunLoopRunSpecific () #39 (null) in GSEventRunModal () #40 (null) in -[UIApplication _run] () #41 (null) in UIApplicationMain () #42 0x105789c28 in hook_uiapplication_main () #43 0x1051a18dc in main at /Users/cuibaoyin3/Desktop/WorkSpace/DQAppModule/Example/DQAppModule/main.m:15 #44 (null) in start ()
内容的提问来源于stack exchange,提问作者bau-yin
相关产品推荐
相关产品推荐

