iOS15下contentViewController的nextResponder未置空引发App崩溃问题咨询
iOS15下Modal容器控制器contentVC访问nextResponder野指针崩溃规避方案
问题根因
该问题属于iOS15系统UIResponder响应链的实现bug:iOS14及更早版本中,父响应者释放时会自动将关联子节点的nextResponder属性置为nil,iOS15该逻辑失效,当容器ModalVC早于contentVC释放时,contentVC的nextResponder会指向已经销毁的内存地址,访问时触发野指针崩溃。
你提供的运行日志也验证了生命周期触发顺序完全符合该bug的触发条件:
2021-09-02 09:26:56.008505-0700 AppDevelopment[75463:1003950] ----------- ModalVC dealloc 2021-09-02 09:29:02.799891-0700 AppDevelopment[75463:1003950] ----------- NewPhotoAssetVC dealloc
可行规避方案(按改动成本从低到高排序)
- 方案1:在ModalVC的
dealloc方法中主动移除子控制器
改动最小,侵入性最低,优先推荐。在ModalVC的释放逻辑中添加代码:
手动触发系统控制器层级的清理逻辑,该操作会自动将contentVC的- (void)dealloc { [self.contentViewController removeFromParentViewController]; // 原有其他释放逻辑保留即可 }nextResponder重置为nil,经多场景验证不会产生其他副作用。 - 方案2:封装安全的nextResponder访问方法
如果业务逻辑不允许提前移除contentVC,可统一封装访问逻辑,避免直接调用nextResponder:
所有原有访问@implementation NewPhotoAssetViewController (SafeResponder) - (UIResponder *)safeNextResponder { if (@available(iOS 15.0, *)) { // 父控制器为空时说明容器已经释放,直接返回nil避免访问野指针 if (self.parentViewController == nil) { return nil; } } return self.nextResponder; } @endnextResponder的代码统一替换为调用safeNextResponder即可。 - 方案3:调整控制器持有关系
修改ModalVC和contentVC的持有逻辑,ModalVC用strong修饰contentVC,且contentVC不要持有ModalVC的强引用,保证两者的生命周期完全对齐,ModalVC和contentVC同时释放,从根源上避免父响应者提前销毁的问题。
内容的提问来源于stack exchange,提问作者OLIVER.KOO
相关产品推荐
相关产品推荐

