SKStoreProductViewController在iOS 15.6 beta5中出现未识别选择器sceneDisconnected:导致崩溃的问题

44
在 iOS 15.6 beta5 和 iOS 16.0 beta 版本中: 当收到 UISceneDidDisconnectNotification 消息时,任何正在使用的 SKStoreProductViewController 实例都会因为无法识别名为 sceneDisconnected 的选择器而崩溃。 -[SKStoreProductViewController sceneDisconnected:]: unrecognized selector sent to instance 0x115161a00 这个崩溃只会在最新的 iOS15.6 和 iOS16 beta 版本中出现。但我在任何官方文件中都找不到这个选择器的名称…… 有什么解决办法吗?或者是我做错了什么?

请通过反馈应用向苹果报告测试版中出现的崩溃问题。 - DarkDust
4
已经报告。 - QianKai
@QianKai 你有重现此问题的步骤或者能提供一个样例项目吗? - fearmint
8个回答

25

看起来这个问题已经在今天发布的iOS 15.6正式版中得到了修复。

2022年9月14日更新:苹果在官方的15.7版本中重新引入了这个崩溃问题。只有当应用程序被强制退出时才会出现,因此不应影响用户。我已经在feedbackassistant.apple.com上向苹果提交了一张工单,并鼓励其他人也这样做。


1
最新的15.6 RC版本,崩溃问题仍然存在。 - leaveslife
@leaveslife 你确定吗?我刚刚更新到最新的15.6 RC版本,没有看到崩溃。 - Lorenzo
5
iOS 15.7 仍存在崩溃问题。 - leaveslife
无法提交问题 - 他们的网站现在出了问题。情况变得越来越糟。这就是当你让一个市场营销人员掌舵而不是产品人员时会发生的事情。安息吧,苹果... - inteist
1
自从版本15.7.1发布以来,我们在Firebase Crashlytics中看到了崩溃率的下降。此外,在筛选iOS版本时,15.7.1不在列表中。这似乎是一个很好的迹象,表明苹果终于在15.7.1中解决了这个问题。 - Martijn
显示剩余4条评论

11

这并不是一个解决方案,但清楚地表明这是苹果需要修复的错误。从一个干净的样本项目开始,你只需要呈现一个SKStoreProductViewController,然后强制退出你的应用程序:

import StoreKit
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let storeKitViewController = SKStoreProductViewController()
        storeKitViewController.loadProduct(withParameters: [
            SKStoreProductParameterITunesItemIdentifier: NSNumber(integerLiteral: 364709193)
        ])
        present(storeKitViewController, animated: true)

        // Force quit after presentation to trigger crash
        // -[SKStoreProductViewController sceneDisconnected:]: unrecognized selector sent to instance
    }

}

我已经通过反馈助手向苹果提交了此问题。


10

iOS16中已修复了崩溃问题

以下是由苹果框架工程师解释:

此崩溃问题发生在iOS/iPadOS 15.7的公开发布以及iOS/iPadOS 16种子版本seed 4之前的种子发布中,但不会在iOS 16的公开发布中出现。 主要发生在应用程序在后台运行且即将被操作系统终止时。因此,这些崩溃不应该对大多数最终用户可见。(唯一的例外情况是iPad上支持多个场景的应用程序,并且用户手动终止场景。) 您的分析数据将显示崩溃率升高,但您的客户不应受此问题影响。 我们正在积极处理此崩溃问题。 [1] 在这种情况下,您应更新到最新版本。

来源:https://developer.apple.com/forums/thread/714464?answerId=729646022#729646022


我也遇到了这些崩溃问题,但我根本没有使用SKStoreProductViewController。为什么会出现这些崩溃呢? - Chris
@Chris,可能被第三方库使用。 - Husam
也许,Firebase? - Chris
在我的应用程序中,admobSKStoreReviewController导致了这个崩溃。 - Husam

7
能够在本地使用相同的堆栈符号重现崩溃,下面的代码可以防止崩溃发生。该代码创建了空函数来处理无法识别的选择器消息,并将该扩展限制为iOS 15.7:
@available(iOS, introduced: 15.7, obsoleted: 16.0)
@objc extension SKStoreProductViewController {
    func sceneDisconnected(_ arg: AnyObject) {}
    func appWillTerminate() {}
}

我不确定这是否完全安全...如果苹果在iOS 15.7.1或15.8上发布新的补丁版本,那怎么办?sceneDisconnected和appWillTerminate将被忽略。 - Vjardel
1
这个的 Objective-C 版本会是什么? - user955853
在Objective-C中,Swift扩展的类比是分类。尽管它应该也适用于Objective-C,就像上面展示的那样,因为它使用@objc进行公开。您的项目需要一个桥接头文件 https://developer.apple.com/documentation/swift/importing-swift-into-objective-c/?language=objc,我会将Foundation和StoreKit的导入添加到上面的代码中。 - MacMark
在我的测试中,这个修复程序可以正常工作,因为它也适用于带有桥接头的Objective-C应用程序。 - MacMark
这是我见过的唯一解决方案。它对我也起作用。我知道它没有考虑15.7.x或15.8,但是我已经等待了很长时间,等待苹果修复这些版本中的错误,我不会再等了...我将在生产发布中包含此内容。谢谢@Chirs。 - Juan Peralta
SKStoreProductViewController的苹果文档(https://developer.apple.com/documentation/storekit/skstoreproductviewcontroller/)明确指出它不支持子类化或嵌入:“防止异常 SKStoreProductViewController类不支持子类化或嵌入,并且必须按原样使用。” - Martijn

2

将以下代码添加到 application(_:didFinishLaunchingWithOptions:) 中(至少在应用程序终止之前)。如果方法不存在,它会在运行时添加方法。

if #available(iOS 15.7, *) {
    if #unavailable(iOS 16.0) {
        class_addMethod(
            SKStoreProductViewController.self,
            Selector(("appWillTerminate")),
            unsafeBitCast({ _, _ in } as @convention(c) (SKStoreProductViewController, Selector) -> Void, to: IMP.self),
            "v@:"
        )
        class_addMethod(
            SKStoreProductViewController.self,
            Selector(("sceneDisconnected:")),
            unsafeBitCast({ _, _, _ in } as @convention(c) (SKStoreProductViewController, Selector, NSNotification) -> Void, to: IMP.self),
            "v@:@"
        )
    }
}

在iOS 15.7中,他们似乎删除了appWillTerminatesceneDisconnected(_:)方法,但忘记了删除将UIApplication.willTerminateNotificationUIScene.didDisconnectNotification观察者添加到NotificationCenter的代码。
编辑:在iOS 15.7.1中,他们似乎重新添加了appWillTerminatesceneDisconnected(_:)方法。因此,我已更新代码,仅在iOS 15.7中添加这些方法。
编辑:他们在iOS 15.7.2中再次删除了这些方法,导致崩溃再次发生。我已恢复代码。

1

这实际上是一种不准确的报告,因为它并没有导致应用程序崩溃。

我复现了所报告的情况:在您的应用程序中点击应用下载广告,在应用内弹出App Store下载页面,然后返回到后台,此时会生成崩溃信息 -- 但实际上并没有发生崩溃,当我返回前台时什么也没变化,一切都正常运作。下次启动应用程序时,将会报告崩溃信息。

因此现在无需做任何事情,只需等待苹果修复即可。


谢谢澄清。如果实际上没有发生崩溃,只是一个报告问题,那就相当令人宽慰。 - tedrothrock

0
自从版本15.7.1发布以来,我们看到Firebase Crashlytics中崩溃的数量有所减少。此外,在筛选iOS版本的崩溃时,版本15.7.1不在列表中。
这似乎是一个好迹象,表明苹果终于在15.7.1中解决了这个问题。
请分享您自己的崩溃报告观察结果,以验证我的假设是否正确。

1
我有数百个崩溃报告,用户使用的是iOS 15.7.2版本,这个问题在15.7.2版本中是否已经解决了? - Bektaş Kart

0

Objective C 版本,通过在 NSObject 上添加一个分类实现。✌

@interface NSObject (crashPrevent)
@end

@implementation NSObject (crashPrevent)
-(void) sceneDisconnected:(id) item {
    return;
}
-(void) appWillTerminate {
    return;
}
@end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接