Tutorial Details
- Technology: iOS SDK
- Difficulty: Intermediate
- Completion Time: 1 Hour
Welcome to the second and final part of the Game Center Tutorial Series. In this tutorial, we will integrate the achievements and leaderboards created with iTunesConnect during part 1 with Objective-C and Xcode.
Step 1: Building the Interface
Before we start with Interface Builder, we first set need to setup some outlets and actions. Open Game_CenterViewController.h and modify the code to read as follows:
#import <UIKit/UIKit.h>
#import <GameKit/GameKit.h>
#import "GameCenterManager.h"
@class GameCenterManager;
@interface Game_CenterViewController : UIViewController <UIActionSheetDelegate, GKLeaderboardViewControllerDelegate, GKAchievementViewControllerDelegate, GameCenterManagerDelegate> {
GameCenterManager *gameCenterManager;
int64_t currentScore;
NSString* currentLeaderBoard;
IBOutlet UILabel *currentScoreLabel;
}
@property (nonatomic, retain) GameCenterManager *gameCenterManager;
@property (nonatomic, assign) int64_t currentScore;
@property (nonatomic, retain) NSString* currentLeaderBoard;
@property (nonatomic, retain) UILabel *currentScoreLabel;
- (IBAction) reset;
- (IBAction) showLeaderboard;
- (IBAction) showAchievements;
- (IBAction) submitScore;
- (IBAction) increaseScore;
- (void) checkAchievements;
@end
First, we import the GameKit framework and the GameCenterManager class. Then, we declare the GameCenterManager class, so we can declare an instance of that class in the @interface. After that we declare the following delegates:
- UIActionSheetDelegate (to use an action sheet)
- GKLeaderboardViewControllerDelegate (to show the leaderboard in our app)
- GKAchievementViewControllerDelegate (to show the achievements in our app)
- GameCenterManagerDelegate (to use the GameCenterManager delegate)
In the @interface we declare some instances and after that we create some actions. Press CMD + S to save the project.
In the “Game Center” folder in the “Project Navigator” click on Game_centerViewController.xib.
Select the View window and choose the background you prefer. I chose “Scroll View Textured Background Color”. Drag 5 “Round Rect Buttons” from the Library to the view. Name and arrange them as shown below. Also drag 2 “Labels” from the Library to the view. Name the first one “Current Score:” and delete the text of the second label.
Select “File’s owner” and open the Connections Inspector.
Connect the actions to the associated buttons, by dragging them to the buttons and select “Touch Up Inside” from the menu.
Drag the “CurrentScoreLabel” outlet to the label with no text and now we are done with the interface.
Step 2: Edit AppSpecificValues.h
Open AppSpecificValues.h and modify the code to read as follows:
//Leaderboard Category IDs #define kLeaderboardID @"1" //Achievement IDs #define kAchievementOneTap @"1_Tap" #define kAchievement20Taps @"20_Taps"
Here we create the constants for our leaderboard and our achievements. As you can see are the ID’s the same as the ones we created in iTunes Connect.
Step 3: Edit Game_CenterViewController.m
First, we are going to synthesize our instances and release them. We also import the “AppSpecificValues” and “GameCenterManager” classes. So open Game_CenterViewController.m and modify the code at the top of the page as follows:
#import "Game_CenterViewController.h" #import "AppSpecificValues.h" #import "GameCenterManager.h" @implementation Game_CenterViewController @synthesize gameCenterManager; @synthesize currentScore; @synthesize currentLeaderBoard; @synthesize currentScoreLabel;
Now modify the viewDidUnload and dealloc methods as follows:
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.gameCenterManager = nil;
self.currentLeaderBoard = nil;
self.currentScoreLabel = nil;
}
- (void)dealloc {
[gameCenterManager release];
[currentLeaderBoard release];
[currentScoreLabel release];
[super dealloc];
}
Step 4: Signing in to Game Center
Scroll down to the “viewDidLoad” method, uncommend it and modify the code as follows:
- (void)viewDidLoad {
[super viewDidLoad];
self.currentLeaderBoard = kLeaderboardID;
self.currentScore = 0;
if ([GameCenterManager isGameCenterAvailable]) {
self.gameCenterManager = [[[GameCenterManager alloc] init] autorelease];
[self.gameCenterManager setDelegate:self];
[self.gameCenterManager authenticateLocalUser];
} else {
// The current device does not support Game Center.
}
}
First we set our currentLeaderboard to our leaderBoard we created in iTunes Connect. After that we set our currentscore to 0. Your high score in Game Center won’t be set to zero, because it only submit scores higher than the previous one. Then we look if Game Center is available on the device the application is running. If Game Center is available we authenticate the local user. If Game Center is not available, nothing happens. You can tell the user that Game Center is not available with a alertview, but I leave it with a comment.
Now you can test your project. Press CMD + R to build and run it. You will get some warnings, but the app will run. If you are already logged in to Game Center, you get the following message: Welcome Back, “Game Center Name”. If you where not logged in to Game Center you get an alert view with the options to create a new account, sign in to an existing account or cancel. If you cancel the leaderboard and achievements won’t work, because you are not signed in to Game Center. The buttons won’t work, because we haven’t made the actions in Xcode.
Step 5: Showing the Leaderboards and Achievements
If you used the simulator, close it and go back to Xcode. Add the following code under the viewDidLoad method:
- (IBAction) showLeaderboard
{
GKLeaderboardViewController *leaderboardController = [[GKLeaderboardViewController alloc] init];
if (leaderboardController != NULL)
{
leaderboardController.category = self.currentLeaderBoard;
leaderboardController.timeScope = GKLeaderboardTimeScopeWeek;
leaderboardController.leaderboardDelegate = self;
[self presentModalViewController: leaderboardController animated: YES];
}
}
- (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
{
[self dismissModalViewControllerAnimated: YES];
[viewController release];
}
- (IBAction) showAchievements
{
GKAchievementViewController *achievements = [[GKAchievementViewController alloc] init];
if (achievements != NULL)
{
achievements.achievementDelegate = self;
[self presentModalViewController: achievements animated: YES];
}
}
- (void)achievementViewControllerDidFinish:(GKAchievementViewController *)viewController;
{
[self dismissModalViewControllerAnimated: YES];
[viewController release];
}
Here, we creae the actions to show the leaderboard and the achievements. We also create 2 methods to go back. The first actions is to show the leaderboard. As you can see we set the timeScope to GKLeaderboardTimeScopeWeek. This means that the leaderboard section is set to “This Week”. There are 3 time scopes and they are straight forward:
- GKLeaderboardTimeScopeToday
- GKLeaderboardTimeScopeWeek
- GKLeaderboardTimeScopeAllTime
If you build and run again, the “Show Leaderboard” and “Show Achievements” buttons will work. Now you can see the Achievements we have created and the associating descriptions and point values. As you can see the leaderbord section is “This Week”. By changing the Time Scope in Xcode you can set the default section to “All Time” or “Today”. The leaderboard says “No Scores”, because we never submitted a score for this leaderboad. Click Done to dismiss the Game Center view.
Step 6: Handle the Score and Achievements
Add the following code under the code we just created:
- (IBAction) increaseScore
{
self.currentScore = self.currentScore + 1;
currentScoreLabel.text = [NSString stringWithFormat: @"%ld", self.currentScore];
[self checkAchievements];
}
Here we create a action to increase your currentScore. We also update our label to the currentScore and call the checkAchievements function to see if we achieved an achievement.
- (void) checkAchievements
{
NSString* identifier = NULL;
double percentComplete = 0;
switch(self.currentScore)
{
case 1:
{
identifier= kAchievementOneTap;
percentComplete= 100.0;
break;
}
case 5:
{
identifier= kAchievement20Taps;
percentComplete= 25.0;
break;
}
case 10:
{
identifier= kAchievement20Taps;
percentComplete= 50.0;
break;
}
case 15:
{
identifier= kAchievement20Taps;
percentComplete= 75.0;
break;
}
case 20:
{
identifier= kAchievement20Taps;
percentComplete= 100.0;
break;
}
}
if(identifier!= NULL)
{
[self.gameCenterManager submitAchievement: identifier percentComplete: percentComplete];
}
}
In this function we look if we achieved an achievement with a switch statement.
First we create a NSString and a double to store our values. In the switch statement we check if the currentscore is 1, 5, 10, 15 or 20. After the switch statement we look if there is something stored in the NSString we created. If there was something stored to that NSString we submit the achievement. We also submit an achievement if you completed it partly. For example, if you tapped the button 10 times you ate on 50% of the “20 Taps” achievement.
We also want to submit or high score, so add the following actions under the code we just created:
- (IBAction) submitScore
{
if(self.currentScore > 0)
{
[self.gameCenterManager reportScore: self.currentScore forCategory: self.currentLeaderBoard];
}
}
Here we check if the score is higher than 0, because we don’t want a score of 0 to be submitted. We submitted our currentScore for our currentLeaderboard.
Build and run the application again and now you can increase your score and submit it. If you click the button 15 times and go to “Show Achievements” you can see that you achieved the “1 Tap” and are on 75% of the “20 Taps” achievement. The Description of the “1 Tap” achievement also changed in the text we gave it when it in iTunes Connect for when it was earned. Close the achievements view and click “Submit Score”, after that click “Show Leaderbaord”. Now you see your score (if your currentScore was higher than 0).
Step 7: Reset the Score and Achievements
dd the following code under the code we just created:
- (IBAction) reset
{
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Are you sure you want to reset your score and achievements?"
delegate:self
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:@"Reset"
otherButtonTitles:nil];
[actionSheet showInView:[self view]];
[actionSheet release];
}
Here we created a action sheet in the reset action. We set the delegate to “self” because we want to do something if you clicked the “reset” button.
Under the “reset” action add the following code:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
[gameCenterManager resetAchievements];
self.currentScore = 0;
currentScoreLabel.text = [NSString stringWithFormat: @"%ld", self.currentScore];
}
}
In this code we look witch button you clicked. You can’t edit the “Cancel” button so we start at a buttonIndex of 0. If you clicked the “Reset” button in the action sheet, the gameCenterManager resets your achievements, the currentScore is set to 0 and we update the currentScoreLabel text.
Step 8: Notify the User of Earned Achievement
Add the following code under the code we just created:
- (void) achievementSubmitted: (GKAchievement*) ach error:(NSError*) error;
{
if((error == NULL) && (ach != NULL))
{
if (ach.percentComplete == 100.0) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Achievement Earned!"
message:(@"%@",ach.identifier)
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
else
{
// Achievement Submission Failed.
}
}
First we check if there wasn’t an error and if there is something stored in “ach”. If this is both true, then we check if ach.presentComplete is 100.0, because we only want to give the user a message if he earned a achievement and not if he is on 50% of an achievement.
If that is true, we show the user that he earned an achievement with an alert view. We set delegate to nil of this alert view, because we don’t need it, we only use the cancel button.
If there was an error or there was nothing stored in ach, then you can give the user an message that the achievement submission failed, but I leave it with a comment.
Build and Run to finish the tutorial. To check if the reset button and the alert view work, click the “Reset Achievements & Score” button. Then increase the score and a alert view should show.
If you earned both achievements and close the app and the delete if from the multitask bar, the currentScore is set to 0 again, because we didn’t store that value. If you increase the score, or apps thinks that you earned the “1 Tap” achievement again, but you already earned it. If you want to occur this, you can save the currentScore value.
Thanks for reading this tutorial about Game Center. If you have questions or comments on this tutorial, leave them in the comments section below or mail me at ballgameios@gmail.com

Great Tutorial!
One question though. Instead of the Alert informing the user the achievment was reach, how do you do the animation of the scroll down alert? It starts at the top of the screen, maybe is 320 x 50, dips and then moves back to the top? Or is that a “custom” alert made by the developer?
That’s a custom alert that you need to make by yourself as developer. It would be nice if Apple provided that alert for your achievements.
I know this post is a little old, but I thought that people should know this.
As of iOS 5.0 there is a Boolean Completion Banner that can be shown.
The code is:
myAchievement.showsCompletionBanner = YES;
This code is shown ONLY when percentComplete = 100.0 and is initially set to NO, which is why you need to set it.
Hey, I set my app up using you tutorial (which is great by the way, thanks a lot), but its not showing ***Sandbox*** when I go to sign in. Therefore wont let me create a sandbox account. All my bundle ID’s are the same and I’ve enabled everything. Have you got any suggestions?
Thanks :)
Thanks for the comments!
If you are testing on a device, are you sure you have the correct profiles installed and used the same App ID for that profile? I thought this was necessary, but I’m not sure. In the simulator it should run correctly.
Thanks for the tutorial. Followed it nicely until the end. I get a message saying that Game is not recognised by Game Center. Any ideas what might be causing this message?
Found the solution. Simply delete the current app from the device and reinstall… Worked like a charm :)
great tutorial, however i am getting stuck
I can connect to to my sandbox gc just fine in the app, the logo appears “Welcome User” my load achievement and leaderboard work just fine…..
however when I try to submit score I get a nslog of “Missed Method”
I understand I would have to send you my code, which I can do, or maybe vice versa, can you public your tutorial code project files? to compare and contrast ?
as my SubmitScore action does..
if(self.currentScore > 0)
{
[self.gameCenterManager reportScore: self.currentScore forCategory: self.currentLeaderBoard];
}
any help would be great,
great tutorial though im like 95% done, one more step and I will have this down packed!
Hey, I belive you can download the source code of the project at the top of this page.
I ran into the same issue. I downloaded your source code and it runs perfectly fine. It is identical to my version line for line and I cannot get the submit button to work.
Thanx! the tutorial worked flawless for me!
Is there any way that the user will be notified (e.g. alertview) that the score submission completed without errors?
Hi there. This is a great tutorial.. I have just implemented Game Center into my 2nd game which is near completion. Thanks a lot for this. Keep up the good work.
I’m glad you like it!
What’s the name of your new game? and the first one?
Hey,
There is a problem. If you run iOS 5, and try to show the achievements view. It crashes with this in the console:
*** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[__NSCFDictionary setObject:forKey:]: attempt to insert nil key’
The NSLog “Missed Method” gets called in GameCenterManager.m and I don’t think it should. Any thoughts on this?
What is the best way to control if I have already earned an achievement?
I have to control this on my game or can I check if the achievement was not earned before submitting it?
in showLeaderboard method there’s a memory leak – you are never releasing “leaderboardController” object
How many leaderboards can we add in one application?
I think your limited to 25 Leaderboards in one application (remember @llamasoft_ox tweeted such a limit when he was counting on 53 – but I don’t think it’s documented anywhere, it just won’t let you add any more when you get to 25)
Nice tutorial!
However, when I change the name of the Leaderboard in iTunes Connect, it doesn’t change when viewed in the app. Also if I add another Leaderboard and change the kLeaderboardID to match, all I get is “Unable to Load” displayed where the scores should be for that Leaderboard. This suggests that once you’ve enabled Game Center, you can’t make changes in iTunes Connect, which seems crazy. And, yes, I’m logged into sandbox mode for Game Center.
Any help is much appreciated!
Must have been a glitch with Game Center sandbox – seems OK now. Thanks again for the tutorial!
Hi great tutorial as others have stated:
However.. I am getting the same issue as some others…
‘Missed Method’ coming up on the console when I try to submit the score
BTW your sample code works perfectly. This is happening only when I swap out your
Bundle ID
KLeaderboard
KAchievenment
also.. I cant find that ‘Missed Method’ NSLog message anywhere in the code which is also confusing me
Any ideas?
Thanks…
EDIT
I forgot to say…
I lets me submit the score once, then after that it does not update.
If I reset my leader board data via iTunes Connect, it will let me submit a new score, but then the same thing happens, it wont let me write in a new one after that…
Game Center only writes a new score if it is higher than the previous one. Maybe this can be the problem?
Is there a way to reset the score in order to submit a lower score ?
Hi..Everything works great! Awesome! But..
Every time I close ta app and open again it completes the challenges again, that shouldn’t happen, right? No one wants to complete the same challenge every time they play the game, how can this be fixed?
I tried saving the currentScoreLabel and loading it using NSUserDefaults. It actually works, the label loads the previous score, but when I click on “increase score” it goes back to 1.
Any ideias?
You will have to save the currentScore int instead of the label. If you open the app you load the saved int and update the label with the score of that int.
I have downloaded the Game Center code , after running on simulator it is not showing the “Welcome back” message nor the the Sign in alert box…What must i do for this? Please help….
Everything works fine except the leaderboards show “no scores”, even though they have been submitted.
is anyone else having this problem?
Same problem! The leaderboard can’t update scores.
I have this same problem! Is there a server glitch with Game Center sandbox for everybody right now?
still cant get it to work???
i wonder maybe if you need 2 scores logged on the leaderboard for it to work? since in the example above there is 2 entries.
for those wondering why you get “no scores”, it seems that you need at least 2 scores for the leaderboard to work.
i created an adhoc provisioning profile and sent the app to a friend, when he submitted a score the leaderboards started to work.
strange.
Hi,
Greetings for the day….
I have read your awesome tutorial, it’s really nice. I have a query
Can we get usernames from game center?
please suggest me
thanks in advance
Sammy
Hi,
Thanks!
In the GKTapper sample code, you downloaded in the first part of this tutorial, they get the username of the person with the highest score. Maybe you can do something with that code.
I think the problem is when running the Code under 4.2 arc is messing with this method
[delegate performSelector:selector withObject: arg withObject: err]; and is making everybody get missed method
i don’t know a work around if anybody knows please let me know
I am also getting this “missed method” error. I can’t figure out what the problem is.
This code doesn’t implement two delegate methods that the gamecentermanager is sending delegate methods to.
If you implement – (void) processGameCenterAuth: (NSError*) error; and – (void) scoreReported: (NSError*) error; in the gamecenterViewController (for this particular code) or the gamecentermanager delegate (in general) the message goes away. So really all the message means is that you are not implementing all of the optional delegate methods and you can essentially ignore it if you want to.
Thank you very much for your tutorial
I have problems on Xcode 4
delete autorelease and //@synthesize delegate;
and run
but
Thread 1 : Program received signal : “SIGABRT”.
how about it :-(
Im pretty sure this is because of how automatic reference counting works now. Instead of deleting the delegate you should have the @property for the delegate be @property (nonatomic, strong) GameCenterManager *gameCenterManager; instead of retain.
hi wonderful tutorial i have inserted it in my project app.. i was wondering how could i call this thing that i did after the game ended?? kindly help pls. thankss
Hi,
I read your tutorial..Its niceee…
I just have a small question. Is there anyway to get the name of the top scorer of my game and his score?
Hello, and thank you for the tutorial. Really a great and easy to follow tutorial.
Everything worked like a charm, except submitting the scores to the leaderboard. It’s not being updated. And I also get the “Missed method” log. I know it’s in GameCenterManager.m file, but that method is not getting called anywhere except callDelegateOnMainThread:, and that is not getting called anywhere at all.
Do you have any leads on this?
The reason for this is that in the code from gktapper it checks if you implement all of the delegate methods in the delegate. The message doesn’t actually do anything, it just tells you that there are things that you can still implement if you want to (since its optional). The two methods that are not implemented are – (void) processGameCenterAuth: (NSError*) error; and – (void) scoreReported: (NSError*) error;
if you implement those two the nslog message goes away.
Also, the scores on the leaderboard are not showing up because you have to submit scores from atleast two accounts (someone else also pointed this out in the comments and that is how i know.)
hi,
Everything works good except the leaderboards show no scores, i have submitted score but leader boards didn’t display score. please any one help to solve this problem. thanks advance…….
All you have to do is submit scores from two accounts. So log out of the game center app and make a new account in the app (the ****sandbox**** create new account thing).
When you submit scores from two accounts you should see the leader board updated with results.
Hi Chris,
I was hoping you could give me some leads on how to fix the issue of the score not updating (but everything else).
I’ve logged out and created 2 new accounts, but it still does not allow me to update the scores.
Was there any other part that I may be missing.
Thanks, Todd
Great tutorial. I get a lot of help from this in implementing Game Center. Thanks for Sharing.
Great tutorial Jeroen !, thanks a lot.
I wanted to ask you something, I’m subclassing a a cocos2d CCScene* object.
this doesn’t support the UIViewController methods, so
[self presentModalViewController: leaderboardController animated: YES];
and
[self dismissModalViewControllerAnimated: YES];
Won’t work, do you know how what the best workaround for this is?
Thanks !
Many Thanks……very useful
how can i implement Leaderboard in c++ ?
How i sign out .i am sign in but now i want to sign in with different id now how i sign out
how i invite friend
Listen to Beyonce’s ‘End Of Time’ DJ mix.
Login to vote (on the upper right corner) & click to login to your FB account.
Don’t forget to click on the ‘Like’ button once you’re redirected after your
registration so that your vote to count. http://bit.ly/wjU5lj
Thanks alot .. helped me find my way through .. check out Steffen Itterheim’s GameKit class as well .. its a great help.
It’s very useful tutorial, thanks.
How can i get friends score of this week from the game center?
Hello friends…
This is great tutorial.
You can hide ” Missed Method” warning by adding this method.Implementation is not much necessary.
Thanks
- (void) processGameCenterAuth: (NSError*) error
{
}
Gajendrasinh K Chauhan
and
– (void) scoreReported: (NSError*) error{
}
Missed Method also appear in output when you click on Reset.So you can add this method
- (void) achievementResetResult: (NSError*) error{
}
Hi everybody.
I have memory leak after calling showLeaderboard method. I am using ARC, but GameCenterManager.h/.m are excluded from ARC. Is there some tutorial, how to change GameCenterManager for using ARC? Thank you.