I'm writing a game app for iOS that optionally uses Game Center with leaderboards for storing highscores. What I'm trying to achieve is:
- first time the app get's started present the Game Center login viewController
- if user logs in successfully everthing's fine
- if user cancels the login process don't bother him anymore (not even on next app start)
- if user selects a function that requires Game Center give him a chance to login
The builtin authenticateHandler doesn't capture a secong login attempt (already reported here) so the login viewController won't come up a second time if it was cancelled once before. So I tried to go this way and save a reference to the login viewController and present it when appropriate. When my highscores button is pressed the login viewController comes up as supposed. When the user cancels the login the viewController is dismissed (but only the first time). That means if he presses the button a second time the login viewController will come up again but can't be dismissed anymore by pressing the cancel button on the upper left corner.
Have a look at my code:
@interface GameKitHelper () {
UIViewController __weak *presentingVC;
}
@property (nonatomic, strong) NSArray *leaderBoards;
@property (nonatomic, strong) completionBlock completion;
@property (nonatomic, strong) UIViewController *gcLoginVC;
@end
- (void) authenticateLocalPlayerForce: (BOOL) force completion: (void (^)(BOOL)) completion {
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
if (localPlayer.authenticated && completion) {
completion(localPlayer.authenticated);
return;
}
self.completion = completion;
if (self.gcLoginVC && !localPlayer.authenticated && [[NSUserDefaults standardUserDefaults] boolForKey: CUserDeactivatedGC] && force) {
[self presentViewController: self.gcLoginVC force: force];
return;
}
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error) {
[self setLastError: error];
if ([GKLocalPlayer localPlayer].authenticated) {
[[NSUserDefaults standardUserDefaults] setBool: NO forKey: CUserDeactivatedGC];
if (self.completion) {
self.completion([GKLocalPlayer localPlayer].authenticated);
}
return;
}
if (viewController) {
self.gcLoginVC = viewController;
[self presentViewController: viewController force: force];
return;
}
[[NSUserDefaults standardUserDefaults] setBool: YES forKey: CUserDeactivatedGC];
[[NSUserDefaults standardUserDefaults] synchronize];
};
}
//on app start don't force presenting login viewController
- (void) viewDidLoad {
[super viewDidLoad];
[[GameKitHelper sharedGameKitHelper] authenticateLocalPlayerForce: NO completion:^(BOOL authenticated) {
if (authenticated) {
[[GameKitHelper sharedGameKitHelper] loadLeaderBoards];
}
}];
}
//when highscores button is pressed do force presenting login viewController
- (IBAction) highscoresButtonTapped: (UIButton *) sender {
[[GameKitHelper sharedGameKitHelper] authenticateLocalPlayerForce: YES completion:^(BOOL authenticated) {
if (authenticated) {
SGGameLeaderboardVC *vc = [[SGGameLeaderboardVC alloc] init];
[self.navigationController pushViewController: vc animated: YES];
}
}];
}