0

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];
        }
    }];
}
Community
  • 1
  • 1
RTasche
  • 2,614
  • 1
  • 15
  • 19
  • Shouldn't presentViewController be called by a viewController? Also you might want to try adding a completion block to presentViewController that does [self dismissViewControllerAnimated:YES completion:nil]; – Shammi Sep 22 '14 at 19:44
  • BTW, I'm trying to solve your first problem, GC authentication needs to happen when user presses leaderboards button. I never thought of caching the viewController that gets passed in. Do you know if that is Kosher by Apple. Will they flag it as an issue and fail cert? – Shammi Sep 22 '14 at 19:48
  • I tried your method and ran into the same issues. It clearly seems like caching the view controller that gets passed in doesn't retain its validity. The second time its brought up, I can't sign in or cancel. – Shammi Sep 22 '14 at 20:23

0 Answers0