Game Center Authentication Handler view controller is always nil - ios

I am trying to set up Game Center in a swift sprite kit game. The following is done in my App Delegate
func authenticateLocalPlayer(){
let localPlayer: GKLocalPlayer = GKLocalPlayer.localPlayer()
localPlayer.authenticateHandler = {(viewController : UIViewController!, error : NSError!) -> Void in
//handle authentication
if (viewController != nil){
self.window?.rootViewController?.presentViewController(viewController, animated: true, completion: nil)
}
else{
if (localPlayer.authenticated){
gameCenterEnabled = true
//Get the default leaderboard identifier.
localPlayer.loadDefaultLeaderboardIdentifierWithCompletionHandler({ (leaderboardIdentifierr: String!, error: NSError!) -> Void in
if (error != nil){
NSLog("%#", [error.localizedDescription])
}
else{
leaderboardIdentifier = leaderboardIdentifierr
}
})
}
else{
gameCenterEnabled = false
}
}
}
}
The problem I am having is that the localPlayer.autheniticateHandler always returns a nil viewController even though my local player is not authenticated. Please let me know what I am doing wrong and how to fix this.

I was having the same problem.
Try deleting the app from the device then go to the device's settings under game centre and enable sandbox.
Then run your game again on the device and it should display the game centre login window.

I tried running my app in simulator and the authentication window came up fine. I am not sure why it is not working on my device however.

Exactly the same happens for me. Tried on multiple devices with the same result. Deleting app/changing Game Centre setting won't help.
Your code looks fine though.
It looks like GC for Swift is totally broken..

Related

replaykit startrecording sometimes never enters completion handler

I am using replay kit to save a video of my screen during gameplay but randomly on occasion startRecordingWithMicrophoneEnabled and recorder.stopRecordingWithHandler never enters the completion handler
it doesn't throw an error, it just runs and hangs indefinitely.
if recorder.available && recorder.microphoneEnabled {
recorder.startRecordingWithMicrophoneEnabled(true) { [unowned self] (error) in
if let unwrappedError = error {
print(unwrappedError.localizedDescription)
} else {
print("called")
self.manager.instructions.text = "Click to Start Game"
}
}
}
if recorder.available && recorder.microphoneEnabled {
print("initiating stop recording")
recorder.stopRecordingWithHandler { [unowned self] (RPPreviewViewController, error) in
print("in completion handler")
if let previewView = RPPreviewViewController {
print("will transition to gameplay video")
previewView.previewControllerDelegate = self
self.presentViewController(previewView, animated: true, completion: nil)
self.sessionHandler.session.stopRunning()
}
}
}
I was getting this same thing. Was working on one device, and not on another. Only difference was the working device was on iOS version 10.1.0 and the other was iOS version 10.0.2 - upgraded to 10.2.0 and it started working immediately.
I had the same problem and just found its cause (or maybe just a cause). If your device is connected to a WiFi that has no internet access this problem occurs. If you connect it to a WiFi that has internet access or disable WiFi it works just fine. I guess when starting a recording, ReplayKit tries to connect to some Apple servers but never reaches them and also never times out. You can observe the same behavior with the App Store. When you are connected to a WiFi without internet it tries to load the store forever and never times out.

Game Center achievements not supported

I am having some problems trying to implement game center achievements into an iOS game. The game already has the player authentication and leaderboards setup and they are working fine. The first error I get is when using this method:
GKAchievementDescription.loadAchievementDescriptionsWithCompletionHandler
It gives me an error which states two things:
"The requested operation could not be completed due to an error communicating with the server."
"App does not support achievements."
Five achievements have been added to iTunes connect so I don't no why it says it doesn't support them. The other issues are when I use this method:
GKAchievement.reportAchievements
When this is called the error in the completion handler is nil, but it returns "no bundle for bundleID: (null)". The achievement banner doesn't show and there is no achievements tab in the game centre view.
The app was recently transferred to another developer but he then wanted some extra features added to it, so I'm using a provisioning profile and developer certificate provided by him so I can test game center and in app purchases properly. It seems like the problem I'm having is relating to the transfer?
So my question is what could be the problem causing the game to 'not support achievements'?
Any help would be much appreciated,
thank you.
Your question is a bit vague, how are those two methods looking exactly in your code. Its hard to help with two lines of a function
You load code should look something like this
/// Load achievements
func loadAchievements(){
print("Loading submitted achievements")
GKAchievement.loadAchievementsWithCompletionHandler( { (achievements, error:NSError?) -> Void in
guard error == nil else {
print("Error loading achievements progress: \(error)")
return
}
guard let validAchievements = achievements else { return }
for achievement in validAchievements {
print("Name: \(achievement.identifier)")
print("Percentage: \(achievement.percentComplete)")
print("Date: \(achievement.lastReportedDate)")
self.achievementsDict.updateValue(achievement, forKey: achievement.identifier!)
}
})
}
You report code should look something like this
/// Save achievement progress
func reportAchievementProgress(percent: Double, achievementID: String) {
guard self.localPlayer.authenticated else { return }
let achievement = self.checkAchievement(achievementID) as GKAchievement? //
if achievement != nil {
achievement!.percentComplete = percent
achievement!.showsCompletionBanner = true
GKAchievement.reportAchievements([achievement!], withCompletionHandler: { (error:NSError?) -> Void in
guard error == nil else {
print(error)
return
}
print("Reported achievement: \(achievementID)) to: \(percent) %")
})
}
}
/// Check achievement
private func checkAchievement(achievementID: String) -> GKAchievement {
var achievement = self.achievementsDict[achievementID]
if achievement == nil {
print("Achievement with no previous progress, saving...")
achievement = GKAchievement(identifier: achievementID)
self.achievementsDict.updateValue(achievement!, forKey: achievement!.identifier!)
}
return achievement!
}
achievementsDict is a dictionary where you cache your achievements.
var achievementsDict = [String: GKAchievement]()
Does this help?

How do you implement shared GKMatchmaker's findMatchForRequest correctly (so GKMatch.expectedPlayerCount == 0)?

When switching to GKMatchmaker from MatchmakerViewController my two sandbox game center accounts running on separate devices (both iPhone 5s) no longer connect into the same match. Both show expectedPlayerCount still above 0.
I followed the RayWenderlich tutorial on creating a multiplayer game with game center. It is supposed to be real time and was working as such. Using a GKMatchmakerViewController it all worked completely fine (both auto-matching and invites). However, as soon as I switched one block of code it no longer works. I've been fiddling with this for awhile now and the apple docs don't seem to help me at all. Anyone know what I might need to do extra?
func findMatchWithMinPlayers(minPlayers: Int, maxPlayers: Int, viewController: UIViewController, delegate: GameKitHelperDelegate) {
if enableGameCenter == false {
return
}
matchStarted = false
gkMatch = nil
gkDelegate = delegate
viewController.dismissViewControllerAnimated(false, completion: nil)
var request = GKMatchRequest()
request.minPlayers = minPlayers
request.maxPlayers = maxPlayers
if pendingRecipients != nil {
request.recipients = pendingRecipients!
}
GKMatchmaker.sharedMatchmaker().findMatchForRequest(request, withCompletionHandler: { (match: GKMatch!, error: NSError!) -> Void in
self.gkMatch = match
self.gkMatch?.delegate = self
println(match)
if self.matchStarted == false && match.expectedPlayerCount == 0 {
self.lookupPlayers()
}
})
}
This only difference between this and what was working is that this has the GKMatchmaker instead of the GKMatchmakerViewController and Delegate.

Parse.com PFUser signUpInBackgroundWithBlock: block not being called on first tap

i am developing an iOS-App with Swift and the parse.com framework and have a big problem with registering new users.
The block of "signUpInBackgroundWithBlock" is not being called on the first tap, although the new user is getting registered. When i am tapping the button a second time, the block gets finally called and i get an error, that the username is already registered.
var newUser = PFUser()
newUser.username = registerView.nicknameTextField.text.trim()
newUser.email = registerView.emailTextField.text
newUser.password = registerView.passwordTextField.text
newUser.signUpInBackgroundWithBlock {
(succeeded: Bool, error: NSError!) -> Void in
self.registerCompletionBlock(succeeded, error: error)
}
Is someone having the same problem and knows a solution for this strange behaviour?
Thanks!
Edit:
The completion block should call the "registerCompletionBlock()" function:
func registerCompletionBlock(succeeded: Bool, error: NSError!) {
if error == nil {
let subscriptionStoryboard = UIStoryboard(name: "Subscription", bundle: nil)
let viewcontroller: UIViewController = subscriptionStoryboard.instantiateInitialViewController() as UIViewController
self.presentViewController(viewcontroller, animated: true, completion: nil)
} else {
if let errorString = error.userInfo?["error"] as? NSString {
println(errorString)
if error.userInfo?["code"] as Float == 202{
let alert = UIAlertView(title: "vergeben", message: "name vergeben", delegate: nil, cancelButtonTitle: "abbrechen")
alert.show()
}
}
}
}
I tried the solution posted previously (eliminating PFUser.enableAutomaticUser()), and the issue persisted.
In case anyone else is still looking for a solution to this issue, try changing the if error == nil to if succeeded == true in the block of signUpInBackground. This worked for me and all is functional in backend.
Its calling at first time, but its taking a little time for calling this .. because its sending data on server in asynchronous. Asynchronous never block the main thread..
Because : -
Asynchronous never block the main thread waiting for a network response.
Asynchronous can be either synchronous on a separate thread, or scheduled in the run loop of any thread.
Asynchronous can be either synchronous on a separate thread, or scheduled in the run loop of any thread.
Synchronous blocks main thread until they complete request.
Because you call the method asynchronous, it takes some time to do it and your main thread doesn't wait for the method to finish. So you should, if you want to show a message or perform a segue, after the registration, put it inside the completion-block:
newUser.signUpInBackgroundWithBlock {
(succeeded: Bool!, error: NSError!) -> Void in
if error == nil {
// Perform a segue, show a message or whatever you want
} else {
let errorString = error.userInfo["error"] as NSString
// Show the errorString somewhere and let the user try again.
}
}
Also if you don't want to do it asynchronous, you can call the signUp() method(without the inBackgroundWithBlock. That way the application waits for the signup to finish until it continues.
i figured it out. Problem was, that i used PFUser.enableAutomaticUser() in the AppDelegate. I removed that line and the signup-block works flawlessly now!

startBrowsingForNearbyPlayersWithHandler() in iOS 8 in Swift

I'm currently making a 2-player strategy board game in Swift and need to connect two iPads over local WiFi or Bluetooth. No matter what I've tried today, I can't get them to detect each other (I've tried over local WiFi and Bluetooth).
Here is my authorization code which runs in the UIViewController when my app first launches (which always returns "Self local player is authenticated." along with the ID:
private func authenticateLocalPlayer() {
var localPlayer = getLocalPlayer()
// If Apple were doing their job right, this is what the proper code should look like:
// var localPlayer = GKLocalPlayer.localPlayer()
if ( !localPlayer.authenticated ) {
localPlayer.authenticateHandler = { (viewController : UIViewController!, error : NSError!) -> Void in
NSLog("Error: \(error)")
if viewController != nil {
// Authenticated?
self.presentViewController(viewController, animated: true, completion: nil)
NSLog("viewController is not nil")
} else if (localPlayer.authenticated == true) {
NSLog("Self local player is authenticated.")
NSLog("My name is \(localPlayer.playerID)")
} else {
NSLog("Not authenticated")
NSLog("Player is \(localPlayer.playerID)")
}
}
} else {
NSLog("Player is already authenticated!")
}
}
and here is my code to detect nearby devices in a separate UIViewController:
override func viewDidLoad() {
devicesLabel.text = "Waiting for devices..."
searchForDevices()
NSLog("Ran searchForDevices()")
}
private func searchForDevices() {
GKMatchmaker.sharedMatchmaker().startBrowsingForNearbyPlayersWithHandler() {
var status = $1 ? "true" : "false"
self.devicesLabel.text = "Reachability changed for player \($0) with status: \(status)"
}
}
No matter what I do with my two iPads (both are model iPad 3), neither one ever sees the other. Am I calling startBrowsingForNearbyPlayersWithHandler correctly?
Also notice that in the authorization code above, I'm using the Objective-C workaround recommended by this post: Game Center not authenticating using Swift, since the "Swift way" of doing that didn't work for me either.
I also ran Spelltower across both devices over local WiFi, so it looks like the hardware is functioning properly. Any idea what could be going wrong here?
I decided to abandon developing this through Game Center and to use Multipeer Connectivity instead.
You are not registering a class to receive invitation updates. You need to register a class and implement methods conforming to the protocol for GKLocalPlayerListener. See my response in this post (it is in Objective-C, but the same concept applies):
Some startBrowsingForNearbyPlayersWithReachableHandler questions

Resources