IOS Game Center GKLocalPlayerListener - ios

I was trying to implement an event listener in a turn based game so a player can receive when his turn is active or when he is invited by a friend. GKTurnBasedEventHandler is deprecated in IOS 7 and i read in the documentation that i should use GKLocalPlayerListener; but that's the extend of it. Is there someone who used it already, because there is no info anywhere.
This is what i tried before, and it does not work.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
[localPlayer authenticateWithCompletionHandler:^(NSError *error)
{
if (localPlayer.isAuthenticated)
{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
[localPlayer registerListener:self];
}
}];
return YES;
}
-(void)handleInviteFromGameCenter:(NSArray *)playersToInvite
{
NSLog(#"test");
}
- (void)player:(GKPlayer *)player receivedTurnEventForMatch:(GKTurnBasedMatch *)match didBecomeActive:(BOOL)didBecomeActive
{
NSLog(#"test");
}

Here is some code that I use in order to register GKLocalPlayerListener
__weak GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error) {
if (viewController) {
[authenticateFromViewController presentViewController:viewController animated:YES completion:^{
[localPlayer registerListener:self];
NSLog(#"Authenticated. Registering Turn Based Events listener");
}];
} else if (localPlayer.authenticated) {
[localPlayer registerListener:self];
NSLog(#"User Already Authenticated. Registering Turn Based Events listener");
} else {
NSLog(#"Unable to Authenticate with Game Center: %#", [error localizedDescription]);
}
};
The documentation states that you should only register for an GKLocalPlayerEventListener once so you could improve this code by checking if you've already registered.
Note that authenticateWithCompletionHandler is deprecated in iOS 6 and they recommend setting the authenticateHandler property like I did above.

I believe you were there. Just this time do a couple of things. Make sure you dont add multiple listeners also before you add a listener, just incase unregister all listeners.
I made sure I only did this once in my whole project, but I get the local player multiple times.
-(void) onLocalPlayerAuthChanged:(GKLocalPlayer*)authPlayer {
[authPlayer unregisterAllListeners];
[authPlayer registerListener:_Whatever_];
}

I might be a little late, but hopefully it will help someone out there...
This is what I do. According to Apple's documentation I create [my] own method that displays an authentication view when appropriate for [my] app.
- (void)authenticateLocalUser
{
if ([GKLocalPlayer localPlayer].authenticated == NO) {
__weak typeof(self) weakSelf = self;
__weak GKLocalPlayer *weakPlayer = [GKLocalPlayer localPlayer];
weakPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error) {
if (viewController != nil) {
[weakSelf showAuthenticationDialogWhenReasonable:viewController];
} else if (weakPlayer.isAuthenticated) {
// Player has been authenticated!
[weakPlayer registerListener:weakSelf];
} else {
// Should disable Game Center?
}
};
} else {
// Already authenticated
[[GKLocalPlayer localPlayer] registerListener:self];
}
}
-(void)showAuthenticationDialogWhenReasonable:(UIViewController *)controller
{
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:controller animated:YES completion:nil];
}
This code is inside a singleton helper class, it might be simplified if you have it on your own class.

Related

Game Centre - Submitting to a Non-Default Leaderboard

So I have an App that has a Game A and Game B.
I have Game Centre implemented correctly for Game A (I used the AppCoda tutorial like I have for every game so far).
Now I'm having troubles getting it to submit the score if Game B is played. I need to the score to be submitted to the second leaderboard created in iTunes Connect.
This is my part of my ViewController that authenticates the User and uses the identifier for the leaderboard etc.
ViewController.h:
-(void)authenticateLocalPlayer{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error){
if (viewController != nil) {
[self presentViewController:viewController animated:YES completion:nil];
}
else{
if ([GKLocalPlayer localPlayer].authenticated) {
_gameCenterEnabled = YES; //added bool indentier to .h
// Get the default leaderboard identifier.
[[GKLocalPlayer localPlayer] loadDefaultLeaderboardIdentifierWithCompletionHandler:^(NSString *leaderboardIdentifier, NSError *error) {
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
else{
_leaderboardIdentifier = leaderboardIdentifier; //added pointer to NSString to .h
}
}];
}
else{
_gameCenterEnabled = NO;
}
}
};
}
Seems my Game B View Controller is scorings/submitting just like Game A, I figured I could just change the above code to this:(to allow for the second identifier):
-(void)authenticateLocalPlayer{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error){
if (viewController != nil) {
[self presentViewController:viewController animated:YES completion:nil];
}
else{
if ([GKLocalPlayer localPlayer].authenticated) {
_gameCenterEnabled = YES; //added bool indentier to .h
_gameCenterEnabled2 = YES;
// Get the default leaderboard identifier.
[[GKLocalPlayer localPlayer] loadDefaultLeaderboardIdentifierWithCompletionHandler:^(NSString *leaderboardIdentifier, NSError *error) {
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
else{
_leaderboardIdentifier = leaderboardIdentifier; //added pointer to NSString to .h
}
}];
// Get the second leaderboard identifier.
[[GKLocalPlayer localPlayer] loadDefaultLeaderboardIdentifierWithCompletionHandler:^(NSString *leaderboardIdentifier2, NSError *error) {
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
else{
_leaderboardIdentifier2 = leaderboardIdentifier2; //added pointer to NSString to .h
}
}];
}
else{
_gameCenterEnabled = NO;
_gameCenterEnabled2 = NO;
}
}
};
}
But for some reason, it won't send the score to the second leaderboard and I can't find any resources/tutorials on how to submit a score to a "non-default" leaderboard...
Ok, so I re-read the Apple Doc and found the solution.
Obviously there can only be ONE default leaderboard (which is authenticated and set in the code in my question)... This doesn't need changing like I originally thought. (I forgot it was used to set the default board).
So what I needed to do was set the Leaderboard identifier to the second leaderboard's identifier (this will be whatever ID you used in iTunes Connect when making the second leaderboard).
I did it in the Game B View Controller when reporting a score like this:
-(void)reportScore{
//set identifier manually as it's not the default leaderboard
GKScore *score = [[GKScore alloc] initWithLeaderboardIdentifier:#"The_GameB_Leaderboard"];
//GKScore *score = [[GKScore alloc] initWithLeaderboardIdentifier:_leaderboardIdentifier2];
score.value = ScoreNumber_B; //Game B HighScore
[GKScore reportScores:#[score] withCompletionHandler:^(NSError *error) {
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
}];
NSLog(#"Reported to Game Center...");
}
There's no need to change the -(void)authenticateLocalPlayer method unless you need to add the GameB bool like I did, in which case you can add it below the GameA Bool:
if ([GKLocalPlayer localPlayer].authenticated) {
_gameCenterEnabled = YES; //added bool indentier to .h
_gameCenterEnabled2 = YES; //GameB bool
.
.
.
}
I hope this helps.

iOS Login again into GameCenter

How can I display the GameCenter Login view again, if a user has canceled during first login attempt.
I am using the following code from raywenderlich tutorial,
-(void) authenticateLocalPlayer {
__weak GKLocalPlayer* localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error) {
[self setLastError:error];
if (localPlayer.authenticated) {
_gameCenterFeaturesEnabled = YES;
currentPlayer = localPlayer;
//NSLog(#"Authenticated User");
[self.delegate2 enableButtonOnAuthentication];
} else if(viewController) {
[self presentViewController:viewController];
} else {
_gameCenterFeaturesEnabled = NO;
}
};
}
The above method is called from viewDidLoad,
[[GameKitHelper sharedGameKitHelper] authenticateLocalPlayer];
[[GameKitHelper sharedGameKitHelper] setDelegate2:self];
If a user cancels the login, I am displaying a message, "to play you must login".
And if tries to call the above method again on a button click the block code does not seems to execute.
Can you point out to what am I doing wrong here?

Game Center Authenticating Problems

Im Developing a new app that uses game center, but unfortunatley im having troubles with game center authentication
here is the authentication code im using:
#interface ViewController ()
// A flag indicating whether the Game Center features can be used after a user has been authenticated.
#property (nonatomic) BOOL gameCenterEnabled;
// This property stores the default leaderboard's identifier.
#property (nonatomic, strong) NSString *leaderboardIdentifier;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self authenticateLocalPlayer];
_gameCenterEnabled = NO;
_leaderboardIdentifier = #"LEADERBOARD ID HERE";
}
- (void)authenticateLocalPlayer {
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error){
if (viewController != nil) {
[self presentViewController:viewController animated:YES completion:nil];
}
else{
if ([GKLocalPlayer localPlayer].authenticated) {
_gameCenterEnabled = YES;
[[GKLocalPlayer localPlayer] loadDefaultLeaderboardIdentifierWithCompletionHandler:^(NSString *leaderboardIdentifier, NSError *error) {
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
else{
_leaderboardIdentifier = leaderboardIdentifier;
}
}];
}
else {
_gameCenterEnabled = NO;
NSLog(#"Game Center Not available");
}
}
};
}
i double checked the app id, the leaderboard identifier and i have game center enabled in itunes connect,i also linked gamekit framework,and imported gamekit in View Controller.h, and i have sandbox mode enabled in game center
im using Xcode 5.0.2 on OS X Mavericks
Could Someone please Help? Its Making me CRAZYY!!
Regards :)
You can use that, I create a simple class for iOS game center in github
Easy Game Center Swift
https://github.com/DaRkD0G/Easy-Game-Center-Swift
For anyone else facing this issue, you need to enable the Game Center capability.

ios game center authentication keeps failing

Basically under ViewController's viewdidload method, I put:
[self authenticateLocalUser];
And authenticateLocalUser method is:
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
if (localPlayer.isAuthenticated == NO)
{
NSLog(#"FAILED");
}
Why doesn't it authenticate? Shouldn't the class method for GKLocalPlayer authenticate automatically? Also, if it does authenticate, should I get the "welcome back __" on the top? I am not getting this banner at all. Is there something I need to do beforehand?
In iOS6 and above you need to present Game Center login view with setAuthenticateHandler api.
Here is Code:
#define CHECK_IOS_LESS_THAN(version) ([[[UIDevice currentDevice] systemVersion] \
compare:version options:NSNumericSearch] == NSOrderedAscending)
- (void) authenticateLocalUser
{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
if (CHECK_IOS_LESS_THAN(#"6.0"))
{
// ios 5.x and below
[localPlayer authenticateWithCompletionHandler:^(NSError *error)
{
[self checkLocalPlayer];
}];
}
else
{
// ios 6.0 and above
[localPlayer setAuthenticateHandler:(^(UIViewController* viewcontroller, NSError *error)
{
if (!error && viewcontroller)
{
[self.navController
presentViewController:viewcontroller animated:YES completion:nil];
}
else
{
[self checkLocalPlayer];
}
})];
}
}
- (void)checkLocalPlayer
{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
if (localPlayer.isAuthenticated)
{
/* Perform additional tasks for the authenticated player here */
[self processGameCenterLoginSuccess];
}
else
{
/* Perform additional tasks for the non-authenticated player here */
[self processGameCenterLoginFaild];
}
}
After adding this code, goto device settings and Reset:
Device: Settings->General->Reset->Reset All Settings
Simulator: Settings->General->Reset->Reset Locations and Privacy
You need to install an authenticateHandler. A section in Apple's Game Center Programming Guide gives a verbatim example. The code starts like this (see that section as linked for full source code):
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = // ...

GKGameCenterViewController analog in ios 5?

iOS 6 provides new view controller to display Game Center info: GKGameCenterViewController.
Does iOS 5.1 provide something similar (except separate controllers for Leader-board and Achievements)?
Here's how I handle both the old and new GameCenter APIs in my app which supports everything between iOS 4 and 7.
I started with the GameCenterManager.m sample code.
1) In GameCenterManager.m, I changed authenticateLocalUser
- (void) authenticateLocalUser
{
if([GKLocalPlayer localPlayer].authenticated == NO)
{
if ([[GKLocalPlayer localPlayer] respondsToSelector: #selector(setAuthenticateHandler:)]) {
[[GKLocalPlayer localPlayer] setAuthenticateHandler:(^(UIViewController* viewcontroller, NSError *error) {
[self callDelegateOnMainThread: #selector(processGameCenterAuth:error:) withArg: viewcontroller error: error];
})];
} else {
[[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error)
{
[self callDelegateOnMainThread: #selector(processOldGameCenterAuth:) error: error];
}];
}
}
}
2) And then in my main view controller, here are my two versions of the authentication handler.
- (void) processOldGameCenterAuth: (NSError*) error; {
// for iOS < 6.0 without the viewcontroller parameter
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
if (localPlayer.isAuthenticated) {
usingGamecenter = TRUE;
[self.gameCenterManager reloadHighScoresForCategory: kOverallLeaderboard];
} else {
usingGamecenter = FALSE;
}
// *** this is where you update your UI after game center login
}
- (void) processGameCenterAuth: (UIViewController*) gameCenterController error: (NSError*) error; {
if (gameCenterController) {
[self presentViewController:gameCenterController animated:YES completion:nil];
} else {
[self processOldGameCenterAuth: error];
}
}

Resources