Displaying a Game Center Leaderboard in SpriteKit - swift

I'm working on a game, and I'm looking for help or the code to display a GameCenter leaderboard in my app when a user clicks a button. I have no clue where to start as all of the other answers seem to be for Obj-C, thanks!
EDIT:
The Below answer worked perfectly, but for those wondering how to do this within SpriteKit, simply add the below methods to the GameViewController and add a Notification Center Observer
NSNotificationCenter.defaultCenter().addObserver(self, selector: "showLeaderboard", name: "showLeaderboard", object: nil)
In your SKScene Class, simply call to that observer.
NSNotificationCenter.defaultCenter().postNotificationName("showLeaderboard", object: nil)
Just to help out those wondering!

Include the GKGameCenterControllerDelegate protocol within your class.
class ViewController: UIViewController, GKGameCenterControllerDelegate
This method dismisses the Game Center view when "Done" is tapped:
func gameCenterViewControllerDidFinish(gcViewController: GKGameCenterViewController!) {
self.dismissViewControllerAnimated(true, completion: nil)
}
This function includes the code that is needed to display the leaderboard:
func showLeaderboard() {
// declare the Game Center viewController
var gcViewController: GKGameCenterViewController = GKGameCenterViewController()
gcViewController.gameCenterDelegate = self
gcViewController.viewState = GKGameCenterViewControllerState.Leaderboards
// Remember to replace "Best Score" with your Leaderboard ID (which you have created in iTunes Connect)
gcViewController.leaderboardIdentifier = "Best_Score"
// Finally present the Game Center ViewController
self.showViewController(gcViewController, sender: self)
self.navigationController?.pushViewController(gcViewController, animated: true)
self.presentViewController(gcViewController, animated: true, completion: nil)
}
You can now trigger the function showLeaderboard by pressing a UIButton:
#IBAction func buttonShowLeaderboard(sender: AnyObject) {
showLeaderboard()
}

You can do it like CeceXX showed, or you can use Easy-Game-Center by DaRkD0G to make it easier. https://github.com/DaRkD0G/Easy-Game-Center-Swift

Related

How to show a specific UIViewController when GKGameCenterViewController is dismissed?

I am presenting a GKGameCenterViewController in an SKScene that inherits from the following protocol.
protocol GameCenter {}
extension GameCenter where Self: SKScene {
func goToLeaderboard() {
let vc = GKGameCenterViewController()
vc.gameCenterDelegate = GameViewController()
vc.viewState = .leaderboards
vc.leaderboardIdentifier = "leaderboard"
view?.window?.rootViewController?.present(vc, animated: true, completion: nil)
}
}
While the GKGameCenterViewController shows up perfect, when I try to dismiss by clicking the X in the top right corner, nothing happens. I assume this is because the reference to my original GameViewController has been deallocated. How can I get this dismissal to work?
According to Apple's Documentation:
Your delegate should dismiss the Game Center view controller. If your game paused any gameplay or other activities, it can restart those services in this method.
This means you need to implement the gameCenterViewControllerDidFinish method in your delegate and dismiss the gameCenterViewController yourself.
You should have something like this in your GameViewController()
func gameCenterViewControllerDidFinish(_ gameCenterViewController: GKGameCenterViewController) {
gameCenterViewController.dismiss(animated: true, completion: nil)
}
In order to present the GKGameCenterViewController on a SKScene, I needed to find the currently displayed UIViewController reference and set this as the delegate. Here is the code I used and it works:
protocol GameCenter {}
extension GameCenter where Self: SKScene {
func goToLeaderboard() {
var currentViewController:UIViewController=UIApplication.shared.keyWindow!.rootViewController!
let vc = GKGameCenterViewController()
vc.gameCenterDelegate = currentViewController as! GKGameCenterControllerDelegate
vc.viewState = .leaderboards
vc.leaderboardIdentifier = "leaderboard"
currentViewController.present(vc, animated: true, completion: nil)
}
}

What is the best way of updating a variable in a view controller from scene delegate?

I am using Spotify SDK. I want to change labels in some view controllers when a user changes his/her player state. Here is my scene delegate:
var playerViewController = MatchViewController()
func playerStateDidChange(_ playerState: SPTAppRemotePlayerState) {
playerViewController.stateChanged(playerState)
}
A view controller:
func stateChanged(_ playerState: SPTAppRemotePlayerState) {
// aLabel.text = playerState.track.name
}
The problem is labels or other outlets are nil when the state is changed because the view controllers are not loaded at that time. How can I fix that? (I tried isViewLoaded)
If you have a more than a few places to update according to a change that occurs at one place use observers. Here's how,
Post notification in SceneDelegate like this:
func playerStateDidChange(_ playerState: SPTAppRemotePlayerState) {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "stateChanged"), object: nil, userInfo: ["playerState": playerState])
}
Observe in ViewControllers like this:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(stateChanged), name: NSNotification.Name("stateChanged"), object: nil)
}
#objc func stateChanged(_ notification: Notification) {
if let playerState = notification.userInfo?["playerState"] as? SPTAppRemotePlayerState {
print(playerState)
}
}
}

swift - How to detect from what ViewController application enter background?

In my swift app I need to know from what screen my application entered background. Im trying to use NotificationCenter this way:
class MainViewController: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(appMovedToBackgroundMain), name: UIApplication.didEnterBackgroundNotification, object: nil)
}
#objc func appMovedToBackgroundMain() {
print("main - App moved to Background!")
}
}
class InitViewController: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(appMovedToBackgroundInit), name: UIApplication.didEnterBackgroundNotification, object: nil)
}
#objc func appMovedToBackgroundInit() {
print("init - App moved to Background!")
}
}
and when I'm press Home button at the MainViewController I got in Xcode's console these lines:
init - App moved to Background!
main - App moved to Background!
and I expected only one line there - main - App moved to Background!. How can I reach this?
On AppDelegate Methods: applicationDidEnterBackground or applicationWillEnterForeground, you can get the top most UIViewController. It is well explained on this question: Get top most UIViewController
You can use following function:
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
Here you can check which controller is on the top in your navigation controller's controller.
print(self.navigationController.topViewController)
When application enter in background state below method will call.
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}

spritekit gamecenter leaderboard - how to show leaderboard from scene?

How can I call my showLeader() function from GameViewController.swift in GameScene.swift ?
this is my showLeader function
func showLeader() {
var vc = self.view?.window?.rootViewController
var gc = GKGameCenterViewController()
gc.gameCenterDelegate = self
vc?.presentViewController(gc, animated: true, completion: nil)
}
You make use of NSNotificationCenter to present the viewController from an SKScene. Remember to add the observer and then post the notification. Don't forget to deinit the NSNotification when you no longer need it or your app will crash.

Swift - FirstViewController and GKGameCenterControllerDelegate

I want to include a GameCenter Leaderboard in my app but I have one problem.
When I want to show LeaderBoard, I use this code :
//shows leaderboard screen
func showLeader() {
var vc = self.view?.window?.rootViewController
var gc = GKGameCenterViewController()
gc.gameCenterDelegate = self
vc?.presentViewController(gc, animated: true, completion: nil)
}
For that, I must had GKGameCenterControllerDelegate in my class like that :
class FirstViewController: UIViewController, GKGameCenterControllerDelegate {
When I do that, I have an error : 'type FirstViewController' does not to conform to protocol 'GKGameCenterControllerDelegate'.
Any solution ?
You need to include the following method:
func gameCenterViewControllerDidFinish(gcViewController: GKGameCenterViewController!)
{
// By tapping on Done, the Game Center window will be dismissed.
self.dismissViewControllerAnimated(true, completion: nil)
}
More info here: https://developer.apple.com/library/mac/documentation/GameKit/Reference/GKGameCenterViewControllerDelegate_Ref/