Search code examples
swiftgame-centergamekit

How to get the user's score from leaderboard? - Swift


I'm working on a game that messes with the leaderboard and the best player score. I would like that when he enters the app it synchronizes with his score saved in the leaderboard, but I didn't find ANYTHING that simply returns the value to me.

I know how to define:

public func setHighScore(score:Int) ->Void {
    if (self.localUser.isAuthenticated) {
        GKLeaderboard.submitScore(score, context: 0, player: self.localUser, leaderboardIDs: ["lbHighScore"], completionHandler: {error in} )
    }
}

What i want is something like this:

public func getHighScore() ->Int{
    if (self.localUser.isAuthenticated) {
        return GKLeaderboardScore      // <- this is the score svaed on leaderboard as integer
    }
    return 0
}

Solution

  • After a lot of work I managed to find!1

    Let's start:

    The way it works when accessing the game center is asynchronous, that is, in parallel. To avoid errors and "delays" when receiving and saving information, I recommend saving in UserDefault. So when you get the data it will be saved in a global variable. You can't just return the value once you get it because it's inside a completionHandler, where the return is Void.

    To access the user information you need to access the GKLeaderboard.Entry class where it has the .score method that saves the score that shows on leaderboard. But the only way to access this method is with the standard functions that will return this information when the user is passed by parameter.

    .

    First step: access the leaderboard with the GKLeaderboard.loadLeaderboards function. In this function, as a parameter:

    • List with the id of the leaderboards that will be accessed

    In addition to the completionHandler which will return two instances:

    • A list of leaderboards
    • Variable for error handling (Error)
    class func loadLeaderboards(
        IDs leaderboardIDs: [String]?, 
        completionHandler: @escaping ([GKLeaderboard]?, Error?) -> Void
    )
    

    .

    Second step: access leaderboard data. For this we will use the GKLeaderboard.loadEntries method. In it we will pass as a parameter:

    • A list of users we will access
    • In which period of the leaderboard it will be accessed

    In addition to the completionHandler which will return two instances:

    • The .Entry class of the local user (is exactly what i want)
    • A list with the .Entry class in case of more than one user
    • Variable for error handling (Error)
    func loadEntries(
        for players: [GKPlayer], 
        timeScope: GKLeaderboard.TimeScope, 
        completionHandler: @escaping (GKLeaderboard.Entry?,[GKLeaderboard.Entry]?, Error?) -> Void
    )
    

    .

    So, mixing the two classes, the function to get the user's score in a given leaderboard is:

    // Function that takes information and saves it to UserDefault
    func getHighScoreFromLeadboard() ->Void {
        // Check if the user is authenticated
        if (GKLocalPlayer.local.isAuthenticated) {
            // Load the leaderboards that will be accessed
            GKLeaderboard.loadLeaderboards(
                            IDs: ["idLeaderboard"]          // Leaderboards'id  that will be accessed
                            ) { leaderboards, _ in          // completionHandler 01: .loadLeaderboards 
                            
                // Access the first leaderboard
                leaderboards?[0].loadEntries(
                                    for: [GKLocalPlayer.local], // User who will be accessed within the leaderboard, in this case the local user
                                    timeScope: .allTime)        // Choose which period of the leaderboard you will access (all time, weekly, daily...)
                                    { player, _, _ in           // completionHandler 02: .loadEntries
                                    
                    // Save on UserDefault
                    UserDefaults.standard.set(player?.score, forKey: "score")
                }
            }
        }
    }