Mac Catalyst 游戏在 GKAchievementInternal showBanner 上崩溃

Mac Catalyst game crashes on GKAchievementInternal showBanner

每次我使用 Mac Catalyst 在 macOS 上向 Game Center 提交成就时,我的游戏都会崩溃:

-[GKAchievementInternal showBanner]: unrecognized selector sent to instance 0x600002616ca0

没有调用堆栈。我为所有 Obj-C 异常设置了一个断点,但它只是在 AppDelegate 中停止了。

在 iOS 和 iPadOS 上一切正常,macOS 上 Game Center 的其余行为似乎没问题。

作为参考,我是这样提交成就的:

    private func submitAchievements(_ aList: [Achievement]) {
        if !isGameCenterEnabled {
            return
        }
        var achievements : [GKAchievement] = []
        for kvp in AchievementFromId {
            if aList.contains(kvp.1) {
                let achievement = GKAchievement(identifier: kvp.0)
                achievement.showsCompletionBanner = true
                achievement.percentComplete = 100.0
                achievements.append(achievement)
            }
        }
        if achievements.count > 0 {
            GKAchievement.report(achievements, withCompletionHandler: { (error: Error?) -> Void in
                if let err = error {
                    NSLog("submitAchievements: \(err.localizedDescription)")
                }
            })
        }
    }

该函数使用这些数据结构:

enum Achievement : Int {
    case
    clearTutorial =   0x00000001,
    clearLevel1   =   0x00000002,
    clearLevel2   =   0x00000004,
}
let AchievementFromId : [String : Achievement] = [
    "Tutorial": .clearTutorial,
    "Level1": .clearLevel1,
    "Level2": .clearLevel2,
]

编辑:

我使用反馈助手提交了反馈。与此同时,我发现的唯一解决方法是在 macOS 上禁用完成横幅:

#if targetEnvironment(macCatalyst)
achievement.showsCompletionBanner = false
#else
achievement.showsCompletionBanner = true
#endif

此外,要重置成就并进行测试,我使用此功能:

    GKAchievement.resetAchievements() { error in
        if let error = error {
            NSLog("resetAchievements: \(error.localizedDescription)")
        } else if let fn = onCompletion {
            syncAchievements() // function that resubmits all the achievements again
        }
    }

这是 macOS Catalina 中的错误。 Apple 已在 macOS 11 Big Sur 中解决此问题(反馈参考:FB7847659)

他们没有计划在 Catalina 上修复此问题。

对于 Catalina,请避免使用 achievement.showsCompletionBanner = false 显示横幅。这看起来有点难看,但我是这样做的:

    #if targetEnvironment(macCatalyst)
        let os = ProcessInfo().operatingSystemVersion
        achievement.showsCompletionBanner = os.majorVersion >= 11
    #else
        achievement.showsCompletionBanner = true
    #endif

请注意,我使用 ProcessInfo() 因为某些原因 if #available(macOS 11.0, *) returns Catalina 也是如此。