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
}
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:
In addition to the completionHandler
which will return two instances:
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:
In addition to the completionHandler
which will return two instances:
.Entry
class of the local user (is exactly what i want).Entry
class in case of more than one userError
)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")
}
}
}
}