I have seen in posts around stack overflow that shows snippets of handling GameCenter authentication. However, none of these solutions address any of the problems that real world use cases cover. Namely, the [GKLocalPlayer localPlayer].authenticateHandler is just a call back of the status, and not much else. It provides a view controller, but there are massive inconsistencies in .authenticated, and error states.
There are a few things I am trying to do: 1. Not pop up the game center login until a feature uses it 2. Try to authenticate silently on app launch 3. Provide some info to the user why GameCenter features are not working 4. Provide a recovery mechanism
Namely if there is an error reported how can I show the login dialog anyways?
I get this error with no viewController:
Case 1:
Error in GameCenterManager::authenticateLocalPlayer [The Internet connection appears to be offline.]
Despite its error message, the device is completely online, as safari loads cnn.com just fine.
Case 2:
Someone closes the login screen because they are not ready, in which case .authenticated comes back as true, viewController remains at nil, yet all game center calls will fail. Why is the [GKLocalPlayer localPlayer].authenticated set to true when it isn't?
Case 3:
Error in GameCenterManager::authenticateLocalPlayer [The operation couldn’t be completed. (NSURLErrorDomain error -1009.)]
This keeps occurring yet there is nothing the app can do for the user. In this case what should the messaging be? Switch apps to Game Center and login there?
Case 4:
Error in GameCenterManager::authenticateLocalPlayer [The requested operation has been canceled or disabled by the user.]
This happens if the user cancels the viewController the app was told to present by apple. Yet, there is also no recovery or detecting this state.
Case 5:
Error in GameCenterManager::createMatch [The requested operation could not be completed because local player has not been authenticated.]
This happens if the user was logged in, but for whatever reason logs out of GameCenter then returns to the app. The app will be told the user is still authenticated when it is clearly not, yet there are no calls I can make to bring up another login.
So essentially, if GameCenter doesn't just silently work, what are we to do as app designers? Alert view and tell them to go login using the game center app and restart the app?
Here is my authentication code:
//******************************************************
// Authenticate
//******************************************************
-(void)authenticateLocalPlayer:(bool)showLogin
{
if( showLogin && self.loginScreen != nil )
{ [[WordlingsViewController instance] presentViewController:self.loginScreen animated:YES completion:nil]; }
if( [GKLocalPlayer localPlayer].isAuthenticated )
{
NSDLog(NSDLOG_GAME_CENTER,@"GameCenterManager::authenticateLocalPlayer LocalPlayer authenticated");
}
__weak GameCenterManager* weakSelf = self;
[GKLocalPlayer localPlayer].authenticateHandler = ^(UIViewController *viewController, NSError *error)
{
if (error != nil)
{
NSDLog(NSDLOG_GAME_CENTER,@"Error in GameCenterManager::authenticateLocalPlayer [%@]", [error localizedDescription]);
}
else
{
if (viewController != nil)
{
NSDLog(NSDLOG_GAME_CENTER,@"GameCenter: No authentication error, but we need to login");
weakSelf.loginScreen = viewController;
}
else
{
if ( [GKLocalPlayer localPlayer].authenticated )
{
NSDLog(NSDLOG_GAME_CENTER,@"GameCenter localPlayer authenticated");
weakSelf.gameCenterAvailable = YES;
weakSelf.localPlayer = [GKLocalPlayer localPlayer];
[weakSelf retrieveFriends];
[weakSelf loadPlayerPhoto:weakSelf.localPlayer];
for ( id<GameCenterDelegate> listener in weakSelf.listeners )
{ [listener onPlayerAuthenticated]; }
}
else
{
weakSelf.gameCenterAvailable = NO;
}
}
}
};
}
This function is called twice: once at app startup to hopefully create a valid login state, and 2nd if the user is not authenticated and they try to use an app feature that requires game center. In this app, it is creating a turn based match or viewing friends