How to make High Score of game to be saved on Leaderboard, with Swift?
Well I see a couple things that can contribute to the issue. First is this method...
func loadHighscore() {
let defaults = NSUserDefaults.standardUserDefaults()
let highscoreLabel = childNodeWithName("highscoreLabel") as! PointsLabel
highscoreLabel.setTo(defaults.integerForKey("highscore"))
}
I don't see anywhere you are setting that so pulling it out won't help much. I added the saving to defaults in the saveHighscore: function bellow.
Second is...
saveHighscore(scoreManager.score)
scoreManager.increment() //<-- Here
showLeader()
You should increment before you save your score.
I would try adding these logs to see if this helps...
func saveHighscore(score:Int) {
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setInteger(score, forKey: "highscore")
defaults.synchronize()
//check if user is signed in
if GKLocalPlayer.localPlayer().authenticated {
println("authenticated")
let scoreReporter = GKScore(leaderboardIdentifier: "Leaderboard_01")
println("ScoreReporter: \(scoreReporter)")
scoreReporter.value = Int64(score)
let scoreArray: [GKScore] = [scoreReporter]
GKScore.reportScores(scoreArray, withCompletionHandler: {error -> Void in
if error != nil {
print("error")
}
else{
println("reported correctly")
}
})
}
}
Hopefully what does or don't print out in the logs plus actually saving your defaults will help. Good luck.
Edit
So it appears the root of the problem is that you have scoreManager (which is a PointsLabel) in your VC but you also have one that is in your Scene. The one in your scene you are updating the score and life is good. When you hit the button you are actually getting the score from the label in your VC that isn't getting updated. So what you really need is to get to that label in your scene to pull out the score.
So the easiest way I can think of getting it to work properly with as little changes to your code is this…
Remove this line completely…
var scoreManager = PointsLabel(num: 0)
and change your action to this...
@IBAction func leaderboard(sender: UIButton) {
let skView = self.view as! SKView
let scene = skView.scene
let scoreManager = scene.childNodeWithName("pointsLabel") as! PointsLabel
saveHighscore(scoreManager.score)
showLeader()
}
Hopefully that fixes everything =)
Swift 3 Game Center Leaderboard does not save the value of the score
I hope you have properly configured leaderboard at https://itunesconnect.apple.com
Please refer below screen
Also refer below code to save score on leaderboard.
func saveScoreOnGameCenter()
{
let leaderboardID = 111
let sScore = GKScore(leaderboardIdentifier: leaderboardID)
sScore.value = Int64(10)
GKScore.reportScores([sScore], withCompletionHandler: { (error: NSError?) -> Void in
if error != nil {
print(error!.localizedDescription)
} else {
print("Score submitted")
}
})
}
Hope this helps you to figure out problem.
How to get the user's score from leaderboard? - Swift
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")
}
}
}
}
Posting score to Game Center leaderboards
First you have to create the GKScore object. Then you set the gkScore.value. Finally, you report the score.
// if player is logged in to GC, then report the score
if GKLocalPlayer.localPlayer().authenticated {
let gkScore = GKScore(leaderboardIdentifier: "leaderBoardID")
gkScore.value = score
GKScore.reportScores([gkScore], withCompletionHandler: ( { (error: NSError!) -> Void in
if (error != nil) {
// handle error
println("Error: " + error.localizedDescription);
} else {
println("Score reported: \(gkScore.value)")
}
}))
}
GameCenter scores are not being posted to the leaderboard
I had the same problem - submitting scores to Game Center by using a new GameKit API available from iOS 14 was never actually saved on the Game Center side (even though there was no any error reported).
Solution which worked for me in the end was simply using a Type Method (with my leaderboardID):
class func submitScore(_ score: Int,
context: Int,
player: GKPlayer,
leaderboardIDs: [String],
completionHandler: @escaping (Error?) -> Void)
instead of the Instance Method counterpart (which apparently has some bug on Apple side):
func submitScore(_ score: Int,
context: Int,
player: GKPlayer,
completionHandler: @escaping (Error?) -> Void)
I was going crazy over this, so I hope this helps someone else.
Saving a highscore for Game Center in Swift 2
According to the prerelease documentation, the method signature has changed to be:
class func reportScores(_ scores: [GKScore],
withCompletionHandler completionHandler: ((NSError?) -> Void)?)
This differs from the old documentation which stated:
class func reportScores(_ scores: [AnyObject]!,
withCompletionHandler completionHandler: ((NSError!) -> Void)!)
Note the change to an optional NSError parameter as well as making the entire handler optional.
So you'll have to change your code to not have the explicit error: NSError!
as your completion block parameter.
Related Topics
Swiftui Hstack with Equal Height
Ckcontainer.Discoverallidentities Always Fails
How to Import Modules Without an Xcode Project in Swift
Why It Is Called the Memberwise Initialiser
Closure Use of Non-Escaping Parameter - Swift 3 Issue
Avplayer Can't Resume After Paused + Some Waiting
Instagram Explorer Searchbar and Tableview
Context Menu Not Updating in Swiftui
How to Hash a String to Sha512 in Swift
Using Animoji/Memoji as Profile Photo
Combined Chart (Line- and Bar Chart) Using iOS-Charts
Cllocation Distancefromlocation (In Swift)
Multidimensional Dictionaries Possible in Swift