Objective C GameCenter authenticateHandler error - ios

I createed a game using this tutorial. When I call authenticateLocalPlayer like so:
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler =
^(UIViewController *viewController, NSError *error) {
[self setLastError:error];
if(viewController != nil) {
[self setAuthenticationViewController:viewController];
} else if([GKLocalPlayer localPlayer].isAuthenticated) {
_enableGameCenter = YES;
} else {
_enableGameCenter = NO;
}
};
I get an error:
-[GKUnauthenticatedPlayerInternal name]: unrecognized selector sent to instance 0x14517e00
but when I add [NSThread sleepForTimeInterval:1] like this:
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
[NSThread sleepForTimeInterval:1];
localPlayer.authenticateHandler =
^(UIViewController *viewController, NSError *error) {
[self setLastError:error];
if(viewController != nil) {
[self setAuthenticationViewController:viewController];
} else if([GKLocalPlayer localPlayer].isAuthenticated) {
_enableGameCenter = YES;
} else {
_enableGameCenter = NO;
}
};
It starts working fine. Is this the correct way to solve the error?

I have the very same problem. And a random sleep doesn't solve it for me.
I find it strange that I can't find any other reference to this problem on the internet. We can not be the only people having this problem, can we?

I found out that what triggered the crash for me was a call to
[self performSelector: #selector(showLabel) withObject: nil afterDelay: 5],
where self is a SKSpriteNode. Note that it was not the moment when the selector was called but at the very call to performSelector, that I got the crash. Also note that the call had nothing at all to do with GKLocalPlayer or Game Center at all.
What solved the problem was to use SKAction instead, like this:
[self runAction:
[SKAction sequence: #[[SKAction waitForDuration:5],
[SKAction performSelector: #selector(showLabel) onTarget: self]]]];
I can't really explain why this does the trick. It seems to be a not too obvious bug with iOS 8.1, since this has never been a problem before.

It seems like the trick is to not call to initiate Game Center from viewDidLoad. If you do call it from there, call it after a delay. Agreed that this is broken in iOS 8.1 and 8.1.1 because it was never an issue before.

It appears that this is an issue with iOS 8.0-8.2. It appears to be resolved in iOS 8.3 in my experimentation. Strangely enough, my other game's code base seems to work consistently throughout (I haven't done exhaustive testing though).

Related

Getting an error with Interstitial Ads (iAd and Spritekit)

I keep getting an error within this section of code:
// Interstitial iAd
-(void)showFullScreenAd {
// Check if already requesting ad
if (requestingAd == NO) {
interstitial = [[ADInterstitialAd alloc] init];
interstitial.delegate = self;
self.interstitialPresentationPolicy = ADInterstitialPresentationPolicyManual;
[self requestInterstitialAdPresentation];
NSLog(#"interstitialAdREQUEST");
requestingAd = YES;
}
}
-(void)interstitialAd:(ADInterstitialAd *)interstitialAd didFailWithError:(NSError *)error {
interstitial = nil;
requestingAd = NO;
NSLog(#"interstitialAd didFailWithERROR");
NSLog(#"%#", error);
}
-(void)interstitialAdDidLoad:(ADInterstitialAd *)interstitialAd {
NSLog(#"interstitialAdDidLOAD");
if (interstitialAd != nil && interstitial != nil && requestingAd == YES) {
//[interstitial presentFromViewController:self];
//[interstitial presentInView:self.view] // I get an error on this line
NSLog(#"interstitialAdDidPRESENT");
if (interstitial.loaded) {
[self requestInterstitialAdPresentation]; //I also get an error on this line too
}
}
}
-(void)interstitialAdDidUnload:(ADInterstitialAd *)interstitialAd {
interstitial = nil;
requestingAd = NO;
NSLog(#"interstitialAdDidUNLOAD");
}
-(void)interstitialAdActionDidFinish:(ADInterstitialAd *)interstitialAd {
interstitial = nil;
requestingAd = NO;
NSLog(#"interstitialAdDidFINISH");
}
Its something to do with this particular line:
[self requestInterstitialAdPresentation];
This is the error I'm getting and I have no idea what this line needs changing to so that the error stops:
-[UIView setShowsFPS:]: unrecognized selector sent to instance 0x146e241a0
Ive gotten this error in the past when working with the same sort of code, it usually appears when I start trying to implement interstitial ads. I seem to be having a lot of trouble trying to implement interstitial ads and I have read a lot of tutorials. I have no idea what I'm doing wrong :( can someone please help?
Regards,
Ryan
setShowsFPS: is a method on SKView, but not on UIView.
Although I don't see the cause in the code you posted, the error means that a UIView instance is being passed to a method that expects an SKView. Set an exception breakpoint to try to figure out where. It's possible that it isn't your code that's triggering the call.

Cocos2D - removeChild not working

In my app I've use the particle designer to produce an animation when bodies collide,
the code is....
-(void)collision
{
for (IceCream *iceCream in [iceDict allValues]) {
if (CGRectIntersectsRect(iceCream.sprite.boundingBox, player.boundingBox)) {
if(actualType == 0)
{
[self increaseLooseCounts];
[self updateLives];
}
else{
[self increaseWinCounts];
[self updateLives];
}
//DEFINING THE PARTICLE ANIMATION
particle = [CCParticleSystemQuad particleWithFile:#"part.plist"]; //alt plist working with rainbow.plist
particle.position = ccp(iceCream.sprite.boundingBox.origin.x,iceCream.sprite.boundingBox.origin.y);
[self addChild:particle z:2];
[particle release];
//CALLING SELECTOR TO END THE PARTICLE ANIMATION
[self performSelector:#selector(killBlast) withObject:nil afterDelay:0.3f];
int icecreamKey = iceCream.sprite.tag;
[self removeChild:iceCream.sprite cleanup:YES];
[iceDict removeObjectForKey:[NSNumber numberWithInt:icecreamKey]];
}
}
}
-(void)killBlast{
[particle removeFromParentAndCleanup:YES];
}
But as soon as the killBlast is called the app crashes.
Please help !!
Remove this line:
[particle release];
You don't own particle object so you don't need to release it. You get it from autoreleased method and then it's retained when becomes added as a child. It will be released once it's removed from parent

Game Center sign in dialogue not appearing

I'm using Apples Game Center to sign the players in at the start of the game, the problem is I've just hit cancel (to test the eventually) and now the dialogue box won't appear anymore, it just keeps going straight through to disabled.
Here's the function I'm using.
-(void) setup
{
gameCenterAuthenticationComplete = NO;
if (!isGameCenterAPIAvailable()) {
// Game Center is not available.
NSLog(#"Game Center is not available.");
} else {
NSLog(#"Game Center is available.");
__weak typeof(self) weakSelf = self; // removes retain cycle error
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer]; // localPlayer is the public GKLocalPlayer
__weak GKLocalPlayer *weakPlayer = localPlayer; // removes retain cycle error
weakPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error)
{
if (viewController != nil)
{
NSLog(#"Try to show ViewController");
[weakSelf showAuthenticationDialogWhenReasonable:viewController];
}
else if (weakPlayer.isAuthenticated)
{
NSLog(#"authenticate player");
[weakSelf authenticatedPlayer:weakPlayer];
}
else
{
NSLog(#"disable");
[weakSelf disableGameCenter];
}
};
}
}
-(void)disableGameCenter
{
}
As you can see disableGameCenter doesn't actually do anything anyway.
Why is it going to disable every time I now run it? (working with the simulator) and how can I get it out of that so the the dialogue appears again? Do I have to manually force the dialogue to appear again somehow?
I had a similar issue under OSX, after you "cancel" the Gamecenter dialog a few times, it stops appearing.
To get it back, run "Game Center", Login and Logout - and then run your game again and the dialogbox will appear again ( it works at least a few times, until you 'cancel' too often ).

Game Center integration with Sprite Kit?

How can I use Game Center or the GameKit Framework with a Sprite Kit Xcode template?
In Sprite kit, it uses Scenes; but normally to view the leaderboards for example you need to "presentModalViewController" but that is not possible in SKView.
And how can I authenticate the player and all that other fun stuff in iOS 6.
Thanks in advance!
You can use "presentModalViewController" by using this code to access the root view controller
UIViewController *vc = self.view.window.rootViewController;
[vc presentViewController: gameCenterController animated: YES completion:nil];
Now you can access your ModelViewController anywhere include in SKScenes. I did it in my newest game and it worked well
Besides, I suggest you use the separate object to control game center like leaderboard and achievement so you can reuse it in your next game.
Here is an updated authenticate local player, but Ravindra's code also works.
- (void) authenticateLocalPlayer
{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error){
if (viewController != nil)
{
//showAuthenticationDialogWhenReasonable: is an example method name. Create your own method that displays an authentication view when appropriate for your app.
//[self showAuthenticationDialogWhenReasonable: viewController];
}
else if (localPlayer.isAuthenticated)
{
//authenticatedPlayer: is an example method name. Create your own method that is called after the loacal player is authenticated.
//[self authenticatedPlayer: localPlayer];
}
else
{
//[self disableGameCenter];
}
};
}
Swift 2.0
func authenticateLocalPlayer() {
let localPlayer = GKLocalPlayer.localPlayer()
localPlayer.authenticateHandler = { (viewController, error ) -> Void in
if (viewController != nil) {
let vc:UIViewController = self.view!.window!.rootViewController!
vc.presentViewController(viewController!, animated: true, completion:nil)
} else {
print ("Authentication is \(GKLocalPlayer.localPlayer().authenticated) ")
GlobalData.loggedIntoGC = true
// do something based on the player being logged in.
GlobalData Swift File:
static var loggedIntoGC:Bool = false
Call Method in your scene where Game Center is being enabled:
ie HUD or GameScene in the
override func didMoveToView(view: SKView)`
authenticateLocalPlayer()
you can authenticate like this
[[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error) {
if (error == nil)
{
static_setEnable( true );
NSLog(#" Authenticate local player complete");
}
else
{
static_setEnable( false );
NSLog(#"Authenticate local player Error: %#", [error description]);
}
}];
}

iOS 6 : Game center authentication

I have a problem with the integration of game center in my app' which use iOS 6 SDK.
In fact I use the sample code from Apple, but it looks like incomplete :
I have tried this code :
-(void) authenticateLocalPlayer {
GKLocalPlayer* localPlayer =
[GKLocalPlayer localPlayer];
localPlayer.authenticateHandler =
^(UIViewController *loginVC,
NSError *error) {
[self setLastError:error];
if ([GKLocalPlayer localPlayer].authenticated)
{
// authentication successful
[self enableGameCenterForPlayer:[GKLocalPlayer localPlayer]];
}
else if (loginVC)
{
// player not logged in yet, present the vc
[self pauseGame];
[self presentLoginVC:loginVC];
}
else
{
// authentication failed, provide graceful fallback
[self disableGameCenter];
}
};
}
But the problem is that enableGameCenterForPlayer, pauseGame, presentLoginVC, disableGameCenter are not implemented methods, and it returns :
Instance method '-enableGameCenterForPlayer:' not found (return type defaults to 'id')
How can I fix this problem ?
Thanks
I use the method [self presentLoginVC:VC] to pass my UITabViewController or UINavigationController the viewController because the block below is not on the main thread.
localPlayer.authenticateHandler = ^(UIViewController *loginVC, NSError *error) {
When you are in a block you should be sure not to change UI elements because you really don't know when it will complete or where you will be in your app. There are probably many ways to do this, but this is my solution.
Below is my UITabBarController 'category' .m file (additions of methods for a class without subclassing) I create the method presentLoginVC and just have it call 'showGameCenterViewController' through my UITabBarController:
#import "UITabBarController+GameKitAdditions.h"
#implementation UITabBarController (GameKitAdditions)
-(void) showGameCenterViewController: (UIViewController *)VC {
[self presentViewController:VC animated:NO completion:nil];
}
-(void)dismissGameCenterViewController:(UIViewController *)VC {
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
As to the other functions:
-(void) enableGameCenterForPlayer:(GKLocalPlayer *) localPlayer;
-(void) disableGameCenter;
-(void) pauseGame;
They could be as simple as just setting a BOOL called enableGameCenter to YES or NO. To get around errors you can just add these prototypes to your .h file and then write the functions just to output something to NSLog() or something.

Resources