I have 2 problems I am experiencing with GameCenter.
If a player is not signed into GameCenter, after if gives you the alert saying you are not signed in, I am no longer able to click any buttons I have on my view.
If a player is signed into GameCenter, after accessing the Leaderboards, pressing “done” will not dismiss the leaderboard view.
Here is my code that relates to GameCenter:
GameViewController:
func authPlayer() { // Gets called in ViewDidLoad
let localPlayer = GKLocalPlayer.localPlayer()
localPlayer.authenticateHandler = {
(view, error) in
if view != nil {
self.presentViewController(view!, animated: true, completion: nil)
}
else {
print(GKLocalPlayer.localPlayer().authenticated)
}
}
}
GameScene:
if gameCenterBtn.containsPoint(location) { // In touches began for touch in touches
saveHighScore(highLevel)
let viewController = self.view!.window?.rootViewController
let gcvc = GKGameCenterViewController()
viewController?.presentViewController(gcvc, animated: true, completion: nil)
}
func saveHighScore(number : Int) {
if GKLocalPlayer.localPlayer().authenticated {
let scoreReporter = GKScore(leaderboardIdentifier: "myLeaderBoardID")
scoreReporter.value = Int64(number)
let scoreArray : [GKScore] = [scoreReporter]
GKScore.reportScores(scoreArray, withCompletionHandler: nil)
}
}
func gameCenterViewControllerDidFinish(gameCenterViewController: GKGameCenterViewController) {
gameCenterViewController.dismissViewControllerAnimated(true, completion: nil)
}
Any and all help would be appreciated
1) Not sure this will help, but your login code is not quite correct. If there is no login view controller doesnt necessarily mean the player is signed in. You are also not handling the optional error. Try this instead.
localPlayer.authenticateHandler = { [unowned self] (viewController, error) in // will handle login changes also
if let error = error {
print(error.localizedDescription)
return
}
if let viewController = viewController {
self.presentViewController(viewController, animated: true, completion: nil)
}
else if self.localPlayer.authenticated {
print("Player authenticated")
}
else {
print("Player not authenticated")
}
}
I am not sure why your gameViewCntroller will not respond. Are you not just loading the first SKScene in your gameViewController.
Could you describe further, maybe with some code, of what does not work afterwards.
2) Its not dismissing the screen because you did not set the delegate.
You code where you are creating the Game Center viewController should look like this
let viewController = self.view?.window?.rootViewController
let gcvc = GKGameCenterViewController()
gcvc.gameCenterDelegate = self // YOU FORGOT THIS LINE
viewController?.presentViewController(gcvc, animated: true, completion: nil)
Related
My rootViewController works and loads fine. However, when I call it using the present(viewControllerToPresent: UIViewController, animated: true, completion: nil) from another viewController I get nothing but a black screen.
I looked all over the stackOverflow but only found solutions for storyboard users. I am doing this programmatically
#objc func handleLogin() {
print("LOGIN BUTTON TOUCHED")
guard let email = emailTextField.text, let password = passwordTextField.text else {
print("Form is not valid.")
return
}
Auth.auth().signIn(withEmail: email, password: password) { (user, error) in
if error != nil {
print(error!)
return
}
let viewController = RootViewController()
*** self.present(viewController, animated: true, completion: nil)
print("Logged in")
}
}
There is nothing wrong with self.present(viewController, animated: true, completion: nil)
I think your RootViewController() is already presented. The black screen you see is might be the one without any data? I am not sure, will need your code for that class.
Another approach you can consider is to replace the real rootViewController from current uiWindow like this
#objc func handleLogin() {
print("LOGIN BUTTON TOUCHED")
guard let email = emailTextField.text, let password = passwordTextField.text else {
print("Form is not valid.")
return
}
Auth.auth().signIn(withEmail: email, password: password) { [weak self] (user, error) in
guard let strongSelf = self else { return }
guard error == nil else { return }
guard let user = user else { return }
UIApplication.shared.keyWindow?.rootViewController = RootViewController()
print("Logged in")
}
}
you've created a new instance(RootViewController) and it must be black .. your not referring to your RootViewController
I was trying to get this to work all last night but it wouldnt. Can anyone help?
I use the following code to display a leaderboard:
gameCenterViewController.leaderboardIdentifier = leaderboardId
This works fine for normal leaderboards, but fails to load any leaderboard sets, when I use the leaderboardSetId. Can you link directly to leaderboard sets and if so how do you do this?
Thanks.
Please do refer below code and cross verify your configuration.
Hope this would help you.
import GameKit
class YourViewController: UIViewController, GKGameCenterControllerDelegate {
var gcEnabled = Bool() // Stores if the user has Game Center enabled
var gcDefaultLeaderBoard = String() // Stores the default leaderboardID
override func viewDidLoad() {
super.viewDidLoad()
self.authenticateLocalPlayer()
}
func authenticateLocalPlayer()
{
let localPlayer: GKLocalPlayer = GKLocalPlayer.localPlayer()
localPlayer.authenticateHandler = {(ViewController, error) -> Void in
if((ViewController) != nil) {
// 1 Show login if player is not logged in
self.presentViewController(ViewController!, animated: true, completion: nil)
} else if (localPlayer.authenticated) {
// 2 Player is already euthenticated & logged in, load game center
self.gcEnabled = true
// Get the default leaderboard ID
localPlayer.loadDefaultLeaderboardIdentifierWithCompletionHandler({ (leaderboardIdentifer: String?, error: NSError?) -> Void in
if error != nil {
print(error)
} else {
self.gcDefaultLeaderBoard = leaderboardIdentifer!
}
})
} else {
// 3 Game center is not enabled on the users device
self.gcEnabled = false
print("Local player could not be authenticated, disabling game center")
print(error)
}
}
}
#IBAction func clickToLeaderBoard(sender: UIButton) {
let gcVC: GKGameCenterViewController = GKGameCenterViewController()
gcVC.gameCenterDelegate = self
gcVC.viewState = GKGameCenterViewControllerState.Leaderboards
gcVC.leaderboardIdentifier = "YourLeaderboardId"
self.presentViewController(gcVC, animated: true, completion: nil)
}
func saveScoreOnGameCenter()
{
let leaderboardID = "YourLeaderboardId"
let sScore = GKScore(leaderboardIdentifier: leaderboardID)
sScore.value = Int64(10)
GKScore.reportScores([sScore], withCompletionHandler: { (error: NSError?) -> Void in
if error != nil {
print(error!.localizedDescription)
} else {
print("Score submitted")
}
})
}
func gameCenterViewControllerDidFinish(gcViewController: GKGameCenterViewController)
{
self.dismissViewControllerAnimated(true, completion: nil)
}
}
Update
Also please do check your leaderboard configuration from back end.
Some good posts are here.
http://www.appcoda.com/ios-game-kit-framework/
https://developer.apple.com/game-center/
https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/GameKit_Guide/GameCenterOverview/GameCenterOverview.html
Having ensured that you have authenticated the local player and your leaderboards set in iTunes Connect, you will need to report your scores to GameCenter ensuring you use 64bit Int.
Now you can add this to display the leaderboard for the local player:
func showGKGameCenterViewController(_ viewController: UIViewController) {
if gameCenterIsDisabled {
print("Local player is not authenticated")
}
let gameCenterViewController = GKGameCenterViewController()
gameCenterViewController.delegate = self
gameCenterViewController.viewState = GKGameCenterViewControllerState.default
viewController.presentViewController(gameCenterViewController, animated: true, completion: nil)
}
I've integrated Game Centre into my app the following way:
When the game loads
func authPlayer(){
let localPlayer = GKLocalPlayer.localPlayer()
localPlayer.authenticateHandler = {
(view, error) in
if view != nil {
self.present(view!, animated: true, completion: nil)
}
else {
print(GKLocalPlayer.localPlayer().isAuthenticated)
}
}
}
And then in the gameOver scene:
func saveHighscore(_ number : Int){
if GKLocalPlayer.localPlayer().isAuthenticated {
let scoreReporter = GKScore(leaderboardIdentifier: "...")
scoreReporter.value = Int64(number)
let scoreArray : [GKScore] = [scoreReporter]
GKScore.report(scoreArray, withCompletionHandler: nil)
}
}
func showLeaderboard() {
let gameCenter = GKGameCenterViewController()
gameCenter.gameCenterDelegate = self
gameCenter.viewState = GKGameCenterViewControllerState.leaderboards
if let gameViewController = self.view?.window?.rootViewController {
gameViewController.show(gameCenter, sender: self)
gameViewController.navigationController?.pushViewController(gameCenter, animated: true)
}
}
Some devices can't find the leaderboard, other devices can find it but only have their score showing etc.
Have I missed something?
Authenticating works fine.
I have the following code which reports score and also displays leaderboard. Everything seems to be okay but when I send it new updated score, it doesn't show the score on leaderboard unless I click on Challenges tab or All Time. Basically, it needs me to click on something else inside leaderboard so the leaderboard can refresh and display the most recent score.
func reportLeaderboardIdentifier(identifier: String, score: Int) {
let scoreObject = GKScore(leaderboardIdentifier: identifier)
scoreObject.value = Int64(score)
GKScore.reportScores([scoreObject]) { (error) -> Void in
if error != nil {
println("Error in reporting leaderboard scores: \(error)")
}
}
}
func displayLeaderboard () {
var gameCenterController: GKGameCenterViewController = GKGameCenterViewController()
gameCenterController.viewState = GKGameCenterViewControllerState.Leaderboards
gameCenterController.gameCenterDelegate = self
self.vc.presentViewController(gameCenterController, animated: true , completion:nil)
}
func gameCenterViewControllerDidFinish(gameCenterViewController: GKGameCenterViewController!) {
gameCenterViewController.dismissViewControllerAnimated(true, completion: nil)
}
I have a problem with Gamecenter. Actually I don't know if its really a problem.
After authenticating my localPlayer the "Welcome"-Banner does not show up.
Why is that? Is that a sign that something is wrong?
I wrote my first app with Swift and SpriteKit with Gamecenter integration. When I open my app, Gamecenter authenticates my localPlayer just fine.
GKLocalPlayer.localPlayer().authenticated // is true
Opening up the Leaderboard works fine too. If I log out of Gamecenter and open my App again it asks me to log in with the view Gamecenter provides.
Showing a GKNotification is also no problem. Pops up right away.
This is my code to authenticate the player:
func authenticateLocalPlayer(){
var localPlayer = GKLocalPlayer()
localPlayer.authenticateHandler = {(viewController, error) -> Void in
if ((viewController) != nil) {
self.presentViewController(viewController, animated: true, completion: nil)
}else{
println("(GameCenter) Player authenticated: \(GKLocalPlayer.localPlayer().authenticated)")
}
}
}
What am I missing?
I'm using this to authenticate with Game Center, and I had never a problem with it (always a welcome banner):
func authenticateLocalPlayer() {
let localPlayer = GKLocalPlayer.localPlayer()
localPlayer.authenticateHandler =
{ (viewController : UIViewController?, error : NSError?) -> Void in
if viewController != nil
{
self.presentViewController(viewController!, animated:true, completion: nil)
}
else
{
if localPlayer.authenticated
{
print("Player authenticated")
self.gameCenterEnabled = true
isAuthenticated = true
localPlayer.loadDefaultLeaderboardIdentifierWithCompletionHandler
{ (leaderboardIdentifier, error) -> Void in
if error != nil
{
print("error", appendNewline: false)
}
else
{
self.leaderboardIdentifier = leaderboardIdentifier
print("\(self.leaderboardIdentifier)")
}
}
} else {
print("Not able to authenticate")
self.gameCenterEnabled = false
if error != nil
{
print("\(error!.description)")
}
else
{
print("error is nil")
}
}
}
}
}