iOS 15 特有Alert Controller相关崩溃无法定位复现问题咨询
该崩溃属于iOS 15.x版本的系统级已知Bug,触发断言的原因为UIKit在处理Alert转场动画时,无法从关联的ViewController中找到对应的AlertController实例,苹果在iOS 16及以上系统版本已完成修复。
常见触发场景
- 短时间内连续弹出多个UIAlertController,前一个Alert的dismiss动画和后一个Alert的present动画出现时序冲突,转场上下文的关联关系被错误清空
- UIAlertController发起present操作后,所属父控制器快速被销毁/进入后台,转场逻辑执行时父控制器已经不持有Alert实例
- 根控制器切换、window层级变更的同时触发Alert弹出,转场上下文的承载控制器被提前替换
可行修复方案
- 全局封装统一的Alert弹出管理队列,确保同一时间仅存在一个活跃的Alert实例,前一个Alert完全执行完dismiss回调后再弹出下一个,避免转场动画重叠
- 弹出Alert前增加校验逻辑,仅当当前presenting控制器处于
viewDidAppear状态、且未被标记为即将销毁时,才执行present操作 - 针对iOS 15版本单独做容错处理,对
+[UIAlertController _alertControllerContainedInViewController:]方法进行Method Swizzle,当系统查询不到对应Alert实例时直接返回nil,阻断断言抛出逻辑,该方案只需要在iOS 15版本生效,高版本无需开启
对应崩溃堆栈信息
LAST EXCEPTION BACKTRACE
CoreFoundation
__exceptionPreprocess libobjc.A.dylib objc_exception_throw Foundation
-[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] UIKitCore
+[UIAlertController _alertControllerContainedInViewController:] UIKitCore
-[_UIAlertControllerAnimatedTransitioning _alertControllerForContext:] UIKitCore
-[_UIAlertControllerAnimatedTransitioning transitionDuration:] UIKitCore
-[UIPresentationController runTransitionForCurrentState] UIKitCore
-[_UIAfterCACommitBlock run] UIKitCore
_runAfterCACommitDeferredBlocks UIKitCore
_cleanUpAfterCAFlushAndRunDeferredBlocks UIKitCore
_afterCACommitHandler CoreFoundation
CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION
CoreFoundation
__CFRunLoopDoObservers CoreFoundation
__CFRunLoopRun CoreFoundation CFRunLoopRunSpecific GraphicsServices GSEventRunModal UIKitCore
-[UIApplication _run] UIKitCore UIApplicationMain MobileBank main main.swift:13 0x000000010b891a24
内容的提问来源于stack exchange,提问作者Igor Shvetsov

