How to show a specific UIViewController when GKGameCenterViewController is dismissed? - swift

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)
}
}

Related

open class UIButton trying to change view controller

So i have a UIButton with its own custom class (open class circlemenu: UIButton), the button is placed on a view controller but the code for the button is in a seperate swift file.
as the custom class produces results i would like it to change from the viewcontroller where the button is physically place to another viewcontroller.
at them moment I'm just getting an error as i can't do like i normally would from a VC item as the button has no self??:
class circlemenu {
var parentViewController:UIViewController!
func presentNewViewController() {
let newViewController = parentViewController.storyboard?.instantiateViewControllerWithIdentifier("YOUR STORYBOARD ID") as UIViewController
parentViewController.presentViewController(newViewController, animated: true, completion: nil)
}
}
i have also tried setting up a relationship with the unbutton and the viewcontroller with the following in my custom class
var parentViewController:UIViewController!
func presentNewViewController() {
let newViewController = parentViewController.storyboard?.instantiateViewControllerWithIdentifier("storyboardID") as UIViewController
parentViewController.presentViewController(newViewController, animated: true, completion: nil)
}
and this in the viewcontroller class
func myCustomClass() {
var customButton = circlemenu()
customButton.parentViewController = self
}
but it just keeps throwing me errors.

Displaying a Game Center Leaderboard in SpriteKit

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

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/

Dismiss Popover after touch

I've created a popover inside my MainViewController when some button its touched using the UIPopoverPresentationController and set like it's delegate like it's showed in the WWDC 2014, in the following way :
MainViewController.swift
class MainViewController : UIViewController, UIPopoverPresentationControllerDelegate {
#IBAction func showPopover(sender: AnyObject) {
var popoverContent = self.storyboard?.instantiateViewControllerWithIdentifier("PopOverViewController") as UIViewController
popoverContent.modalPresentationStyle = UIModalPresentationStyle.Popover
var popover = popoverContent.popoverPresentationController
popoverContent.preferredContentSize = CGSizeMake(250, 419)
popover!.delegate = self
popover!.sourceView = self.view
popover!.sourceRect = CGRectMake(180,85,0,0)
self.presentViewController(popoverContent, animated: true, completion: nil)
}
}
The popover have a View inside it and when the View it's clicked with a Tap Gesture Recognizer I show LastViewController using a modal segue, the modal segue is created through the Interface Builder, not in code using an action to present the another LastViewController
Once the LastViewController is dismissed and I'm back in the MainViewController the popover remains open.
Inside the PopOverController I only have the default code nothing more.
LastViewController.swift
#IBAction func dismissVIew(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
The above code is used to dismiss the LastViewController once the button inside is touched.
Storyboard
How can I dismiss the popover once the another LastViewController it's visible, or before the another LastViewController should be opened?
Thanks in advance
I have already answer same problem over here.
There scenario is different but solution is same
You have to write code for dismiss presented view controller on completion of current view controller.
Write below code on your dismissVIew method of LastViewController.swift
var tmpController :UIViewController! = self.presentingViewController;
self.dismissViewControllerAnimated(false, completion: {()->Void in
println("done");
tmpController.dismissViewControllerAnimated(false, completion: nil);
});
Download link
In your button action on the FinalViewController, have you tried:
#IBAction func dismissMe() {
//this should tell the popover to tell the main view controller to dismiss it.
self.presentingViewController!.presentingViewController!.dismissViewControllerAnimated(false, completion: nil)
}
here is how I would do it.
I usually use lazy initialization for the PopoverViewController and it's ContentViewController
lazy var popoverVC: UIPopoverController = {
let vc = UIPopoverController(contentViewController: self.contentVC)
vc.delegate = self
return vc
}()
lazy var contentVC: UIViewController = {
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("ContentViewController") as UIViewController
vc.modalInPopover = true
return vc
}()
inside my contentViewController I hold a reference to the UIPopoverController.
var popoverVC: UIPopoverController!
then when I show the popover i just assign the popoverController to the contentViewController
#IBAction func showPopover(sender: UIButton) {
contentVC.popoverVC = self.popoverVC
let viewCenterRect = self.view.convertRect(self.view.bounds, toView: self.view)
popoverVC.presentPopoverFromRect(CGRectMake(CGRectGetMidX(viewCenterRect), CGRectGetMidY(viewCenterRect), 1, 1), inView: self.view, permittedArrowDirections: UIPopoverArrowDirection.allZeros, animated: true)
}
finally I dismiss the Popover programmatically inside an #IBAction
#IBAction func dismissPopover(sender: AnyObject) {
popoverVC.dismissPopoverAnimated(true)
}
Inside the viewcontroller you can override viewWillAppear()
Inside of this block dimiss it
override public func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
_viewToDismiss.removeFromSuperView()
}
But the above code assumes you have a reference to the PopOver object, which I don't think is good practice based on how you described the problem.
Rather, why not have the viewcontroller that created the PopOver be responsible for destroying it. Put this in the class that listens for the button touch (which I also assumes creates the PopOver as well)
- (void)viewWillDisappear:(BOOL)animated
{
_popOver.removeFromSuperView()
}
The popover have a View inside it and when the View it's clicked with a Tap Gesture Recognizer I show another ViewController using a modal segue.
As far as I understand from what you say, you should be able to call dismissViewControllerAnimated(_:completion:) from the action associated to your tap gesture recogniser. This will dismiss the popover you presented calling:
self.presentViewController(popoverContent, animated: true, completion: nil)
You can call this method on the popover view controller itself, depending on what is more convenient for you:
The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, it automatically forwards the message to the presenting view controller.
Based on #Jageen answer
Swift 4.2
let tmpController :UIViewController! = self.presentingViewController;
self.dismiss(animated: false, completion: {()->Void in
print("done");
tmpController.dismiss(animated: false, completion: nil);
});