Search code examples
iosobjective-cswiftgame-centergame-center-leaderboard

Present GameCenter authenticationVC again


I'm facing a little issue here and I hope someone will help me figure out what is wrong.

*The test project presented below can be find here : http://goo.gl/wz84aA (FR) or https://goo.gl/0m8LrZ (Mega.NZ) *

I'm trying to present to the user the authentification view controller proposed by apple for the GameCenter feature. More precisely, re-present it if he canceled it on the first time.

I have a game with a storyboard like that :

Storyboard

GameNavigationController :

class GameNavigationController: UINavigationController {
    override func viewDidLoad() {
        super.viewDidLoad()

        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("showAuthenticationViewController"), name: PresentAuthenticationViewController, object: nil)

        GameKitHelper.sharedInstance.authenticateLocalPlayer()
    }

    func showAuthenticationViewController() {
        let gameKitHelper = GameKitHelper.sharedInstance

        if let authenticationViewController = gameKitHelper.authenticationViewController {
            self.topViewController.presentViewController(authenticationViewController, animated: true, completion: nil)
        }
    }

    deinit {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
}

MenuViewController :

class MenuViewController: UIViewController {
    @IBAction func didTapLeaderboardBTN() {
        // TRY 2
        //if ( !GameKitHelper.sharedInstance.gameCenterEnabled) {
            GameKitHelper.sharedInstance.authenticateLocalPlayer()
        //} else {
            GameKitHelper.sharedInstance.showGKGameCenterViewController(self)
        //}
    }
}

GameKitHelper :

import GameKit
import Foundation

let PresentAuthenticationViewController = "PresentAuthenticationViewController"

let singleton = GameKitHelper()

class GameKitHelper: NSObject, GKGameCenterControllerDelegate {

    var authenticationViewController: UIViewController?
    var lastError: NSError?
    var gameCenterEnabled: Bool

    class var sharedInstance: GameKitHelper {
        return singleton
    }

    override init() {
        gameCenterEnabled = true
        super.init()
    }

    func authenticateLocalPlayer () {

        let localPlayer = GKLocalPlayer.localPlayer()
        localPlayer.authenticateHandler = { (viewController, error) in

            self.lastError = error

            if viewController != nil {
                self.authenticationViewController = viewController
                NSNotificationCenter.defaultCenter().postNotificationName(PresentAuthenticationViewController, object: self)
            } else if localPlayer.authenticated {
                self.gameCenterEnabled = true
            } else {
                self.gameCenterEnabled = false
            }
        }
    }

    func showGKGameCenterViewController(viewController: UIViewController!) {

        if ( !self.gameCenterEnabled ) {
            println("Local player is not authenticated")

            // TRY 1
            //self.authenticateLocalPlayer()

            return
        }

        let gameCenterViewController = GKGameCenterViewController()

        gameCenterViewController.gameCenterDelegate = self

        gameCenterViewController.viewState = .Leaderboards

        viewController.presentViewController(gameCenterViewController, animated: true, completion: nil)
    }

    func gameCenterViewControllerDidFinish(gameCenterViewController: GKGameCenterViewController!) {
        gameCenterViewController.dismissViewControllerAnimated(true, completion: nil)
    }
}

What is currently working :

  • if the user is previously logged-in (within the GameCenter app) then he's able to open the leaderboard view ;
  • if the user wasn't logged-in then he's prompted to log-in when the game navigation controller is loaded (and then open the leaderboard).

What is NOT currently working :

  • if he cancel three time the authentification, then the authentification won't appear anymore (even at launch) ; // Apparently a known "problem", not "fixable"
  • if the user cancel his authentification, when he tries to load the leaderboard the authentification won't appear again.

I tried 2-3 things as you can see in the commented code above, but none of them is working ; I can't make the authentification view appear again.

PS : My code is written in Swift, but help in Objective-C is welcomed as well.


Solution

  • As you have found out, if the Game Center authentication dialog is canceled 3 times, then you can't bring it back without resetting the device.

    There is another "security feature" built into Game Center which does not allow an app to re-authenticate if the user has already canceled the dialog without leaving the app. So for your authentication dialog to show, the user must leave and then re-enter your app.

    There is really no way around it. What I've done in a couple of projects is to display a message to the user:

    Game Center not available. Please make sure you are signed in through the Game Center app

    I will show that message after trying to authenticate and if Game Center isn't available or the user is not signed in.