Game Center not authenticating using Swift

Andy Heard picture Andy Heard · Jun 4, 2014 · Viewed 7.3k times · Source

I'm trying to authenticate the local player using swift, but every time I get a false value for the .authenticated property. Here is the code I'm using, it is called by the main view controller when the app starts.

func authenticateLocalPlayer(){
  var localPlayer = GKLocalPlayer()
  localPlayer.authenticateHandler = {(viewController, error) -> Void in
    if viewController {
      self.presentViewController(viewController, animated: true, completion: nil)
    }else{
      println((GKLocalPlayer().authenticated))
    }
  }
}

It brings up the log in view just fine, but when I enter a test account login, it just returns the GKLocalPlayer().authenticatedas false. The bundle identifier in iTunes Connect and the info.plist are exactly the same, as is the version and the app name. Everything is enabled for Game Center on iTunes Connect and in Xcode, but I have a feeling it's not a coding error, it's a setup error in the app record somewhere but I can't for the life of me find where.

After further tinkering, I'm getting this error:

Error Domain=GKErrorDomain Code=15 "The requested operation could not be completed because this application is not recognized by Game Center." UserInfo=0x17006b300 {NSLocalizedDescription=The requested operation could not be completed because this application is not recognized by Game Center.}

I have no idea why this is the case, the bundle ID, name and versions all match...

Any help would be greatly appreciated.

Answer

marmph picture marmph · Jun 5, 2014

This issue has been resolved by Apple - just call:

GKLocalPlayer.localPlayer()

Previously, the issue was that GKLocalPlayer() does not return the GKLocalPlayer singleton, but instead returns a new GKLocalPlayer instance.

If you were on the Xcode 6 BETA, you could add a C function or Objective-C method that returns the real GKLocalPlayer singleton, then use this in Swift. This is the gist of my workaround (with bad naming conventions):

In an Objective-C header:

GKLocalPlayer *getLocalPlayer(void);

In an Objective-C implementation:

GKLocalPlayer *getLocalPlayer(void) {
    return [GKLocalPlayer localPlayer];
}

In your bridging header:

#import "ThatHeader.h"

Then whenever you need to access the GKLocalPlayer singleton in Swift, you can just use getLocalPlayer() instead of GKLocalPlayer(). It's probably a better idea to stick that in an method of a GKLocalPlayer category.

However, this is no longer necessary as detailed above.