Swift 4中Firebase的FIRAScreenViewReporter崩溃问题求助
_dispatch_sync_wait死锁崩溃 从你提供的重复崩溃日志来看,这个问题的核心是Firebase Analytics的FIRAScreenViewReporter模块在处理屏幕事件上报时发生了队列死锁,具体触发点在_dispatch_sync_wait调用,下面是详细分析和可行的排查方向:
崩溃核心定位
崩溃栈顶的libdispatch.dylib 0x183370bfc _dispatch_sync_wait + 600是典型的死锁特征——意味着代码在同步等待某个队列执行完成,但该队列当前正被当前线程占用,导致互相等待无法推进。
而连续两次出现的-[FIRAScreenViewReporter screenParameters]调用,说明这个方法内部很可能存在嵌套的dispatch_sync调用,且目标队列就是当前正在执行该方法的队列,形成了死锁闭环。
触发路径梳理
崩溃发生在页面跳转完成后的生命周期流程中:
- 从
UINavigationController viewDidAppear:开始,Firebase通过分类方法-[UIViewController(FIRAScreenClassName) fira_viewDidAppear:]拦截了页面显示事件 - 随后进入
FIRAScreenViewReporter的setCurrentViewController:方法,这里使用了_dispatch_queue_barrier_sync_invoke_and_complete做同步屏障调用 - 最终在调用
screenParameters时触发死锁,导致崩溃
可行的排查与解决方案
1. 优先升级Firebase SDK版本
这个死锁问题大概率是Firebase Analytics旧版本的已知bug,建议你将Firebase相关依赖(尤其是FirebaseAnalytics)升级到最新的稳定版本。很多类似的屏幕上报队列竞争问题在后续版本中已经被修复。
2. 检查自定义屏幕上报逻辑
如果你在项目中手动调用了Firebase的屏幕上报API(比如logEvent(withName: .screenView, parameters:...)或setScreenName(_:screenClass:)),请检查这些调用的时机:
- 避免在
viewDidAppear等生命周期方法中重复上报,和Firebase的自动上报逻辑冲突 - 确保所有手动上报都在主线程执行,不要在后台线程触发屏幕事件
3. 临时禁用自动屏幕上报验证
可以通过修改Info.plist临时关闭Firebase的自动屏幕追踪:
<key>FIREBASE_ANALYTICS_AUTO_SCREEN_REPORTING_ENABLED</key> <false/>
之后手动控制屏幕上报,观察是否还会出现崩溃。如果崩溃消失,说明问题确实出在自动上报的逻辑中,此时可以结合升级SDK或者调整手动上报的方式来解决。
4. 排查项目队列调度的特殊处理
如果你的项目对主线程或自定义队列做了特殊的调度限制(比如自定义了RunLoop逻辑、或者在主线程做了长时间阻塞操作),可能会干扰Firebase内部的队列操作。确保主线程保持流畅,不要在主线程执行耗时同步任务。
原始崩溃日志
以下是重复出现的崩溃栈实例:
0. Crashed: FIRAScreenViewReporter 0 libdispatch.dylib 0x183370bfc _dispatch_sync_wait + 600 1 Farley 0x100312424 -[FIRAScreenViewReporter screenParameters] + 4333757476 2 Farley 0x100312424 -[FIRAScreenViewReporter screenParameters] + 4333757476 3 Farley 0x100306bac +[FIRAnalytics logEventWithOrigin:isPublicEvent:name:parameters:] + 4333710252 4 Farley 0x100306a78 +[FIRAnalytics logInternalEventWithOrigin:name:parameters:] + 4333709944 5 Farley 0x100304f6c -[FIRASessionReporter logUserEngagementEventWithScreen:] + 4333703020 6 Farley 0x100305200 -[FIRASessionReporter handleScreenDidChangeFromScreen:toScreen:] + 4333703680 7 Farley 0x100313294 -[FIRAScreenViewReporter postScreenDidChangeNotificationWithPreviousScreen:newScreen:] + 4333761172 8 Farley 0x100313014 51-[FIRAScreenViewReporter setCurrentViewController:]_block_invoke + 4333760532 9 libdispatch.dylib 0x183362a14 _dispatch_client_callout + 16 10 libdispatch.dylib 0x18336b618 _dispatch_queue_barrier_sync_invoke_and_complete + 56 11 Farley 0x100312cac -[FIRAScreenViewReporter setCurrentViewController:] + 4333759660 12 Farley 0x100312840 -[FIRAScreenViewReporter viewControllerDidAppear:] + 4333758528 13 Farley 0x100313e2c -[UIViewController(FIRAScreenClassName) fira_viewDidAppear:] + 4333764140 14 UIKit 0x18cf885d0 -[UINavigationController viewDidAppear:] + 96 15 UIKit 0x18cee0670 -[UIViewController _setViewAppearState:isAnimating:] + 852 16 UIKit 0x18cee0bdc -[UIViewController _endAppearanceTransition:] + 228 17 UIKit 0x18d21054c -[UIPresentationController transitionDidFinish:] + 840 18 UIKit 0x18d3f59b4 -[_UICurrentContextPresentationController transitionDidFinish:] + 44 19 UIKit 0x18d214428 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke_2 + 188 20 UIKit 0x18cfd8910 -[_UIViewControllerTransitionContext completeTransition:] + 116 21 UIKit 0x18cfd8700 -[UITransitionView notifyDidCompleteTransition:] + 252 22 UIKit 0x18cfd8198 -[UITransitionView _didCompleteTransition:] + 1128 23 UIKit 0x18cfd7d1c -[UITransitionView _transitionDidStop:finished:] + 120 24 UIKit 0x18ceffbb4 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 312 25 UIKit 0x18ceff8c0 -[UIViewAnimationState animationDidStop:finished:] + 296 26 UIKit 0x18ceff960 -[UIViewAnimationState animationDidStop:finished:] + 456 27 QuartzCore 0x187a38e14 CA::Layer::run_animation_callbacks(void*) + 284 28 libdispatch.dylib 0x183362a14 _dispatch_client_callout + 16 29 libdispatch.dylib 0x18336f698 _dispatch_main_queue_callback_4CF$VARIANT$mp + 1016 30 CoreFoundation 0x18398e544 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE + 12 31 CoreFoundation 0x18398c120 __CFRunLoopRun + 2012 32 CoreFoundation 0x1838abe58 CFRunLoopRunSpecific + 436 33 GraphicsServices 0x185758f84 GSEventRunModal + 100 34 UIKit 0x18cf2b67c UIApplicationMain + 236 35 Farley 0x1001bd99c main (FilterMode.swift:21) 36 libdyld.dylib 0x1833c856c start + 4
内容的提问来源于stack exchange,提问作者Anders Cheow

