Got this message suddenly in my app -
<Info>: 22:20:44.800330 com.apple.AVConference: GKSConnSettings: set server: {
"gk-cdx" = "17.173.254.218:4398";
"gk-commnat-cohort" = "17.173.254.220:16386";
"gk-commnat-main0" = "17.173.254.219:16384";
"gk-commnat-main1" = "17.173.254.219:16385";
}
Where does it comes from?
In iOS 6.0 + this log will show up as soon as your localPlayer is authenticated, i.e. set
[GKLocalPlayer localPlayer].authenticateHandler = ^(UIViewController *viewController, NSError *error) {
if (viewController != NULL) {
// present the viewController now
} else if ([GKLocalPlayer localPlayer].isAuthenticated) {
NSLog(#"Already authenticated");
} else {
NSLog(#"Not authenticated, disable GameCenter");
}
};
and if necessary present the viewController to log into GameCenter
My first instinct tells me it could be related to your environment. Are you working from a virtual machine by chance? This happened to be my case.
Related
I used demo in ios 9 for testing game center, [GKLocalPlayer localPlayer] returns the right information, but when i used in my app, it returns nil. I cannot find why.The demo and app use the same bundle identifier and signature.
Anyone knows the answer, please help the despairing me!
sorry for poor English, wish you can understand them.
Can it caused by complex thread?
Please answer me!!!!!
Beg your answer!!!!!
SOS!!
See a code sample
//here is some of codes i use;
- (void)authenticateLocalUser : (bool)bLoginGame{
if(!gameCenterAvailable)
{
return;
}
NSLog(#"Authenticating local user...");
if ([GKLocalPlayer localPlayer].authenticated == NO)
{
[GKLocalPlayer localPlayer].authenticateHandler=^(UIViewController* viewcontroller, NSError *error) {
if(viewcontroller != nil)
{
if(bLoginGame)
{
[g_sharedInstanceAppDelegate.viewController presentViewController:viewcontroller animated:YES completion:nil];
}
}
else if(error == nil && [GKLocalPlayer localPlayer].authenticated)
{
if(bLoginGame)
{
NSString* uid = [GKLocalPlayer localPlayer].playerID;
NSString* name = [GKLocalPlayer localPlayer].displayName;
GameCenterLoginCallback(uid, name, nil, false);
}
}
else
{
NSLog(#"LOGIN FAILED!");
if(bLoginGame)
{
GameCenterLoginCallback(nil, nil, error, true);
}
}
};
}
else{
NSLog(#"Already authenticated!");
if(bLoginGame)
{
NSString* uid = [GKLocalPlayer localPlayer].playerID;
NSString* name = [GKLocalPlayer localPlayer].displayName;
GameCenterLoginCallback([GKLocalPlayer localPlayer].playerID, name, nil, false);
}
}
sad for no one give me the right answer...
but today i suddenly found the reason why [GKLocalPlayer localPlayer] information is nil.....so i write here, for some one may need it...
Edit scheme->Run->Diagnostics->unselect [enable address sanitizer].
This will fix the question.But donot know why caused that.
I created a class of NSObject and I have this authenticate function in it:
-(void)authenticateLocalUser {
if(!gameCenterAvailable) { return; }
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
__weak GKLocalPlayer *blockLocalPlayer = localPlayer;
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error){
NSLog(#"authenticateHandler");
if (viewController != nil)
{
NSLog(#"viewController != nil");
}
else if (blockLocalPlayer.isAuthenticated)
{
NSLog(#"localPlayer already authenticated");
//do some stuff
}
else
{
NSLog(#"local player not authenticated");
// not logged in
}
};
}
Its the new version i looked up , but its not displaying the Game Center login form.
Im calling this method in my AppDelegate.m if you need this information.
I think I have to put something in there when the player is not logged in like get the login form. But I don't know how.
Thanks for any help!
There are two things you need. First, you need to check error. If it is set, the viewController will usually be nil and your code will incorrectly assume that you're logged in and communicating happily Game Center. You may appear logged in based on cached credentials, but in most cases, you won't actually be seeing current data from the server, you'll just have access to whatever data was last cached on the device.
Second, you have to present the viewController to the user if they're not logged in. Try this:
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error)
{
NSLog(#"authenticateHandler");
if (error)
{
//Examine the error. IOS may show you as "authenticated" based on
//cached credentials, but you probably can't really communicate with
//game center in any meaningful manner
}
else if (viewController != nil)
{
//You're not logged in, show the login viewController
NSLog(#"viewController != nil");
UIViewController *mainVC = [[[[UIApplication sharedApplication]delegate] window] rootViewController];
[mainVC presentViewController:viewController animated:NO completion:^
{
//the login view controller has been dismissed. Did it work?
if ([GKLocalPlayer localPlayer].authenticated)
{
//Yes, Login worked. enable whatever comes next after successful login
}
else
{
//No, login failed or was canceled.
}
}];
}
else if (blockLocalPlayer.isAuthenticated)
{
NSLog(#"localPlayer already authenticated");
//do some stuff
}
else
{
NSLog(#"local player not authenticated");
// not logged in
}
};
I was wondering how to know when Game Center sign in form is finished by the user. I am doing Facebook sign in automatically but I need to wait for Game Center login to finish. Is there any way of knowing that?
-(void) authenticateLocalPlayer {
GKLocalPlayer* localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler =
^(UIViewController *viewController,
NSError *error) {
[self setLastError:error];
if (localPlayer.authenticated) {
_gameCenterFeaturesEnabled = YES;
NSLog(#"local Player Info: %#",localPlayer);
[[UserManager sharedInstance] setGameCenterId:localPlayer.playerID];
[[UserManager sharedInstance] setUserName:localPlayer.alias];
[self retrieveFriends];
} else if(viewController) {
[self presentViewController:viewController];
} else {
_gameCenterFeaturesEnabled = NO;
}
};
}
-(void) setLastError:(NSError*)error {
_lastError = [error copy];
if (_lastError) {
NSLog(#"GameKitHelper ERROR: %#", [[_lastError userInfo]
description]);
}
}
-(UIViewController*) getRootViewController {
return [UIApplication
sharedApplication].keyWindow.rootViewController;
}
-(void)presentViewController:(UIViewController*)vc {
UIViewController* rootVC = [self getRootViewController];
[rootVC presentViewController:vc animated:YES completion:nil];
}
Here is a quote from authenticateHandler documentation
The authenticate handler will be called whenever the authentication
process finishes or needs to show UI. The handler may be called
multiple times. Authentication will happen automatically when the
handler is first set and whenever the app returns to the foreground.
If the authentication process needs to display UI the viewController
property will be non-nil. Your application should present this view
controller and continue to wait for another call of the
authenticateHandler. The view controller will be dismissed
automatically.
Possible reasons for error:
1. Communications problem
2. User credentials invalid
3. User cancelled
So the block will be called multiple times,
For example if user is not logged in, a view-controller will be passed to this block, after you present it and user submits the form, he block will be executed once again.
Here is code that handles authentication:
- (void)authenticateLocalPlayer
{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
__weak typeof(localPlayer) weakLocalPlayer = localPlayer;
localPlayer.authenticateHandler =
^(UIViewController *viewController, NSError *error)
{
if (error) {
// Something happened, handle it...
return;
}
__strong typeof(weakLocalPlayer) strongLocalPlayer = weakLocalPlayer;
if (viewController) {
// Just show it, user needs to submit the form
return;
}
if (strongLocalPlayer.isAuthenticated) {
// User completed login, do FB login
} else {
// GameKit is disabled, show guide to enable it
}
};
}
I am making a game in Swift. I want to be able to post the users' score using GameCenter, so that scores from all my users' can be seen. However, I have spent the past day trying to figure out how to do this, but I haven't found any helpful instructions.
I am pretty new to iOS programming, and Swift, and of the very little amount of information on this subject, it's all written in Objective-C.
Can anyone help me integrate GameCenter into my app, so that I can post users scores to the leaderboards for people to see?
EDIT: I have already created a GameCenter leaderboard on iTunesConnect.
EDIT 2: I have tried following this tutorial: http://www.appcoda.com/ios-game-kit-framework/ and converting it to Swift. I have converted this:
-(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;
// Get the default leaderboard identifier.
[[GKLocalPlayer localPlayer] loadDefaultLeaderboardIdentifierWithCompletionHandler:^(NSString *leaderboardIdentifier, NSError *error) {
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
else{
_leaderboardIdentifier = leaderboardIdentifier;
}
}];
}
else {
_gameCenterEnabled = NO;
}
}
};
}
into this:
func authenticateLocalPlayer() {
var localPlayer : GKLocalPlayer!
localPlayer.authenticateHandler = {(viewController : MenuViewController!, error : NSError!) -> Void in
if viewController != nil {
self.presentViewController(viewController, animated: true, completion: nil)
} else {
if localPlayer.authenticated {
self.gameCenterEnabled = true
localPlayer.loadDefaultLeaderboardIdentifierWithCompletionHandler({ (leaderboardIdentifier : String!, error : NSError!) -> Void in
if error != nil {
println(error.localizedDescription)
} else {
self.leaderboardIdentifier = leaderboardIdentifier
}
})
} else {
self.gameCenterEnabled = false
}
}
}
}
but it crashes on this line:
localPlayer.authenticateHandler = {(viewController : UIViewController!, error : NSError!) -> Void in
The Error message is:
fatal error: unexpectedly found nil while unwrapping an Optional value
I can't believe how hard this is!
Your specific issue has nothing to do with Game Center and is happening because you have the line var localPlayer : GKLocalPlayer!.
You're declaring an implicitly unwrapped optional and then using it right away. It's value is nil in the subsequent line when you try to set localPlayer.authenticateHandler.
Instead you should instantiate GKLocalPlayer like so:
var localPlayer = GKLocalPlayer()
Note that there are currently issues with Game Center and Swift. Your code is going to work but localPlayer.authenticated never gets set to true. This issue is tracked here:
http://www.openradar.me/17825348
Credit to: http://www.stuarticus.net/blog/2014/7/game-center-authentication-and-swift
for filing the radar ticket.
You can use that, I create a simple class for iOS game center in github
Easy Class Game Center Swift
https://github.com/DaRkD0G/Easy-Game-Center-Swift
I'm in sandbox mode implementing game center in my application. The problem comes when I log to gameCenter, in some devices works fine in some others I get a GKErrorCanceled without even get the interface shown.
This devices don't have any user logged in gameCenter so it's not related to have a non sandbox account logged. My code is:
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
//First we try the new iOS6 authentification method for gamekit, if it's not implemented we will use the deprecated one
if ([localPlayer respondsToSelector:#selector(setAuthenticateHandler:)]) {
if (localPlayer.isAuthenticated) {
this->setState(connectionLoged);
this->getDelegate().socialConnectionDidSucceedLogin(*this);
return;
}
else if(!localPlayer.isAuthenticated && localPlayer.authenticateHandler){
this->setState(connectionClosed);
this->getDelegate().socialConnectionDidFailToLogin(*this, std::string("The user already resign to login"));
return;
}
else{
localPlayer.authenticateHandler = ^(UIViewController* viewController, NSError* error){
if (localPlayer.isAuthenticated)
{
_name = [localPlayer.displayName UTF8String];
_userId = [localPlayer.playerID UTF8String];
[GKPlayer loadPlayersForIdentifiers:localPlayer.friends withCompletionHandler:^(NSArray *players, NSError *error) {
for (GKPlayer* player in players) {
if ([player isFriend]) {
NSDictionary* dict =
#{#"displayName" : player.displayName,
#"alias" : player.alias,
#"playerID" : player.playerID};
AttrDictionary* playerInfo = [dict hydraAttrDictionary];
SocialFriend* socialfriend = this->getNewFriendInstance(*playerInfo);
this->addFriend(socialfriend);
delete playerInfo;
}
}
this->getDelegate().socialConnectionDidSucceedLogin(*this);
this->setState(connectionLoged);
}];
}
else if(viewController){
UIViewController* rootViewController = (UIViewController*) [UIApplication sharedApplication].keyWindow.rootViewController ;
[rootViewController presentModalViewController:viewController animated:YES];
}
else{
if(error){
this->getDelegate().socialConnectionDidFailToLogin(*this, std::string([error.description UTF8String]));
}
else{
this->getDelegate().socialConnectionDidFailToLogin(*this, std::string("User cancelled login"));
}
}
};
}
}
//deprecated at IOs 6 authentification method
else
[localPlayer authenticateWithCompletionHandler:^(NSError *error) {
if (localPlayer.isAuthenticated)
{
_name = [localPlayer.displayName UTF8String];
_userId = [localPlayer.playerID UTF8String];
[GKPlayer loadPlayersForIdentifiers:localPlayer.friends withCompletionHandler:^(NSArray *players, NSError *error) {
for (GKPlayer* player in players) {
if ([player isFriend]) {
NSDictionary* dict =
#{#"displayName" : player.displayName,
#"alias" : player.alias,
#"playerID" : player.playerID};
AttrDictionary* playerInfo = [dict hydraAttrDictionary];
SocialFriend* socialfriend = this->getNewFriendInstance(*playerInfo);
this->addFriend(socialfriend);
delete playerInfo;
}
}
this->getDelegate().socialConnectionDidSucceedLogin(*this);
this->setState(connectionLoged);
}];
}
else{
NSString* errorString = [error localizedDescription];
this->getDelegate().socialConnectionDidFailToLogin(*this, std::string([errorString UTF8String]));
this->setState(connectionClosed);
}
}];
I need the code compatible with iOS 6 and iOS 5 so you will see I have the two implementations. For iOS 6 the completion handler returns with an UIViewController null and the error as I say. I'm afraid that in production it happends the same. In the simulator all works fine.
PS- You will find some c++ code, it's because I implement a c++ wrapper for GameCenter as my game is write in cocos2dx...
When someone cancels out of the interface to sign in to game center, it will give you GKErrorCanceled. The third time in a row that they cancel, it will warn them that it will disable game center.
If they do choose to disable game center, then it won't show the interface anymore, and it will just give you GKErrorCanceled instead.
Once game center has been disabled, the only way to sign in is by going into the actual game center app.
The 3 times in a row could be in any app or any combination of apps that use game center, and game center will be disabled for all apps that use game center. The 3 times in a row restarts every time they sign in to game center.
This is for both sandbox and non-sandbox.
This is for both ios 5 and ios 6.