Mac Catalyst game crashes on GKAchievementInternal showBanner

0

Every time I submit an achievement to Game Center on macOS, using Mac Catalyst, my game crashes with this:

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

No call stack. I set a break point for all the Obj-C exceptions but it's just stopped in the AppDelegate.

Everything is fine on iOS and iPadOS, and the rest of the Game Center behaviour on macOS seems to be fine.

For reference, this is how I submit the achievements:

    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)")
                }
            })
        }
    }

That function uses these data structures:

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

Edit:

I filed a feedback with the Feedback Assistant. In the meantime, the only workaround I found is disabling the completion banners on macOS:

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

Also, to reset the achievements and test this, I use this function:

    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
        }
    }
game-center
mac-catalyst
asked on Stack Overflow Jun 30, 2020 by endavid • edited Jul 3, 2020 by endavid

1 Answer

0

This was a bug in macOS Catalina. Apple has resolved this in macOS 11 Big Sur (Feedback reference: FB7847659)

They don't have plans to fix this on Catalina.

For Catalina, just avoid showing banners with achievement.showsCompletionBanner = false. This looks a bit ugly, but I did this:

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

Note that I use ProcessInfo() because for some reason if #available(macOS 11.0, *) returns true in Catalina as well.

answered on Stack Overflow Nov 16, 2020 by endavid

User contributions licensed under CC BY-SA 3.0