iOS15.6/16 beta中SKStoreProductViewController sceneDisconnected崩溃求解
问题复现信息
- 影响系统版本:iOS 15.6 beta5、iOS 16.0 beta系列版本
- 崩溃触发条件:系统发送
UISceneDidDisconnectNotification通知时,当前处于活跃状态的SKStoreProductViewController实例会触发崩溃 - 崩溃日志特征:
-[SKStoreProductViewController sceneDisconnected:]: unrecognized selector sent to instance 0xxxxxxx - 补充说明:公开官方文档中无
sceneDisconnected:选择器的相关说明,正式版iOS系统暂未复现该问题
问题性质判断
该问题不属于开发者接入配置操作不当导致,属于苹果beta版本系统的内部实现bug:
系统在上述两个beta版本中,错误地给SKStoreProductViewController实例注册了UISceneDidDisconnectNotification通知的回调,回调方法指定为sceneDisconnected:,但SKStoreProductViewController类本身并未实现该方法,最终触发找不到选择器的崩溃。sceneDisconnected:属于苹果未公开的内部方法,开发者无需、也不应该主动调用该方法。
可行修复方案
方案1:Method Swizzling 兜底添加空实现(推荐)
通过分类给SKStoreProductViewController动态添加sceneDisconnected:的空实现,在方法找不到时兜底响应,不影响原有业务逻辑,Objective-C项目实现代码如下:
#import <StoreKit/StoreKit.h> #import <objc/runtime.h> @implementation SKStoreProductViewController (BetaCrashFix) + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ SEL crashSelector = NSSelectorFromString(@"sceneDisconnected:"); // 仅当类本身未实现该方法时才添加,避免覆盖系统后续修复的正式逻辑 if (![self instancesRespondToSelector:crashSelector]) { IMP emptyIMP = imp_implementationWithBlock(^(id target, NSNotification *note) { // 空实现,仅做崩溃拦截,无额外业务逻辑 }); class_addMethod(self, crashSelector, emptyIMP, "v@:@"); } }); } @end
Swift项目可通过桥接文件接入上述逻辑,或在runtime初始化阶段通过等价逻辑添加方法实现。
注意:可额外增加系统版本判断,仅在iOS 15.6 beta、iOS 16.0 beta的版本区间内生效,等苹果正式版系统确认修复该问题后,可移除此段兜底代码。
方案2:临时规避逻辑
不使用runtime方案的情况下,可全局监听UISceneWillDisconnectNotification通知,收到通知时主动dismiss当前正在展示的SKStoreProductViewController实例,避免系统发送断开通知时命中未实现的回调触发崩溃。
内容的提问来源于stack exchange,提问作者QianKai
相关产品推荐
相关产品推荐

