How to get from SKScene to UIViewController? - ios

I am new to programming and I am trying to build a simple game using Swift and SpriteKit. It looks good now but I have a little problem to solve. How do I get from a SKScene (Game) to a UIViewController in the Storyboard?
My game looks like this. In the Storyboard i have 3 views (Main menu, About and Game Over) and 1 SKScene (Game). When the player clicks on the play button in the main menu he gets to the game SKScene. When the player fails I want to get to a new UIViewController where I can link 2 buttons (back to main menu and restart).
I don't know how to do this. I will also accept Objective-C if you don't know in Swift.

For others encountering this problem down the road:
self.view?.window?.rootViewController
will return a UIViewController object when called in a SKScene.

Related

Using multiple ViewControllers and SKScene in Swift

Below I have two and a half different ways to set up my game using view controllers and SKScene. The half I haven’t put so much time into yet as I’m hoping one of these other solutions will work.
described in more detail below are:
MainViewController -> GameViewController(holds the SKScene)
GameViewController(holds the SKScene) - Using Protocols
0.5 Two SKScenes/Two swift custom classes.
Number 1
MainViewController -> GameViewController(holds the SKScene)
when the game is over in the SKScene - I want to dismiss GameViewController and return to MainViewController.
I’ve had no luck in getting that to work. I’ve tried dismissing the view controller and the closest I’ve come is dismissing the SKScene using something like(in SKScene:
self.view?presentScene(nil)
or
self.dismiss(animated: false, completion: nil)
self.presentingViewController?.dismiss(animated: false, completion: nil)
but I’m unable to go back to the MainViewController. I’ve tried creating a reference to the GameViewController to pop it like:
weak var gameViewController:GameViewController? = GameViewController()
Unfortunatly, I’m unable to find the right functions to dismiss it properly.
After a lot of searching without finding an answer I thought I would try a different method.
Number 2
GameViewController(holds the SKView) then have the GVC hold the buttons and labels that I wanted and show the scene on top. this was a fail as The buttons and labels don’t have a zPositions and appeared on top of the scene.
I tried doing .isHidden = true on them before calling the scene and that seemed to work but when I dismiss the scene and attempt to change them back to .isHidden = false (tried using protocols) I was unable to get it to work. (was going off of what stvn describes How to reference the current view controller from a sprite kit scene)
I suspect this second way could be a good way of doing it but maybe I’m just not approaching it correctly.
Number 0.5
then finally what I’m thinking about now is just making the second scene to “flip” back and forth between. I believe this is the recommended way of doing it but I’m not really sure how to approach it. If I did this version. I would like to have a gameScene.swift/gameScene.sks for each view (perhaps using something like presenting a uiviewcontroller for skscene.
I would prefer the first way with having two view controllers as I think that the layout for my game would be much easier to do using a few view controllers.
My least preferred method is multiple scenes as I’m just not that great with sprite kit and math for laying out everything.
Is the first method even possible? If so any suggestions would be great. If not what would be the recommended way of doing this?
In method 1 if your MainViewController is a UINavigationController you should have no issues pushing and popping whatever other ViewControllers you need to.
e.g. in GameViewController:
self.navigationController!.popViewController(animated: true)

MKMapView Not Behaving Correctly

I have two UIViewControllers, both of which are embedded in UINavigationControllers. UIViewController A contains a button that, when clicked, presents UIViewController B which contains a MKMapView. UIViewController also contains a button that dismisses the view to go back to UIViewController A. But, the issue is that when I dismiss UIViewController B, UIViewController shows up but is frozen. Nothing is interactable and user interaction is disabled. However, I do see a semaphore_wait_trap when I pause the program in the debugger after the app freezes. But the weirdest thing is that the app works fine and does not freeze when I disconnect from XCode and use it then. So is this an XCode issue or am I doing something wrong? Any help is greatly appreciated!

Segue only working once?

Hi I made a game using SpriteKit and wanted to add a leaderboard using a UITableView. My segues are working perfectly from my GameViewController to the TableViewController and back. However I can only do this once. Once I am back to my GameViewController, tapping the same button wont take me to the TableViewController for the second time. Why is this happening?
I set it up so when a certain SKSpriteNode is tapped it segues to the the TableViewController. Currently I am using this line of code to segue from the GameViewController to the TableViewController (This code is within GameScene.swift)
self.view!.window!.rootViewController!.performSegueWithIdentifier("showScores", sender: self)
I then setup a Back button within a navigation bar and created a segue back to the GameViewController (by dragging the BarButtonItem to the GameViewController and selecting presentModally). Some help would be appreciated. Thanks!
I think you are segueing to the leaderboard, segueing back, but in the process adding the main game view to the stack rather than removing the leaderboard, so when you try to segue again, it is not the visible game scene that receives the call.
Try using this rather than a segue in your leaderboard code (where you ask to segue back to the game scene):
self.dismissViewControllerAnimated(true, completion: nil)
If that doesn't work use a delegate to ask the game scene to dismiss the leaderboard.
Edit: I was rambling and maxed out my word count for the comment, so thought I'd add my explanation here!
Think of the stack as a pile of paper, where each piece of paper is a viewController, the topmost piece being the one that's visible (naturally). When you segue or present a viewController modally you are adding a viewController to the stack or 'adding a piece of paper to your pile'. It is generally then a bad idea to segue to and from like you were doing because you are adding more and more 'pieces of paper' to the stack. You tend to get memory problems and/or irritating bugs :P. Instead what is considered best practice for programmatically going back is to do one of two things: if you are using a navigationController you should call popViewControllerAnimated, or if you aren't, like in this case, you should use dismissViewControllerAnimated. Both these functions take the topmost 'piece of paper' off the stack entirely. Fixing that problem of continually adding the viewControllers to the stack. If any of that was confusing (I'm writing this on my phone so could be!) just send me a comment or a message and I'll try to explain better! :)

Using UIButtons in storyboard to navigate towards previously used Scene

I am making an app in xCode using Swift, and I need help with something. How do I program a UIButton that I added on a Scene on my Storyboard to navigate towards the previously used Scene (there are more than one Scenes in my app).For Example; if Im in scene3 and I'm navigated towards the scene with the UIButton, how can I program it to take me back to scene3 instead of the main menu? Or if I were in Scene2 and was navigated to the Scene with the UIButton, and I want it to take me to Scene2 instead of Scene3 or Main Menu.
Thank you
The Blue Scenes represent the levelScenes that will lead to the redScene after the level is done, however I want the UIButton to lead back to the exact same levelScene after it is pressed
You can use:
self.dismissViewControllerAnimated(true, completion: nil)
To dismiss the current view controller from the view hierarchy.
So you would create an IBAction for your UIButton that would execute that method.

How to make view controllers go to random view controllers

At the moment i have 9 game levels. After you complete the first game you go to results screen. After you press continue the results screen goes to second game and this continues until last game. I wanted to know if there is a way to make it so that after you press continue in the results screens it will go to random game level(or view controller). Sorry if my terminology is bad but i just started coding with objective-c and not sure if what im asking is possible without having to make a lot of segues for each level(view controller).Now i have 20 view controllers in my story board. 1.Intro screen. 1.Name submitting screen. 9. game levels and 9 corresponding result screens.
Why don't you keep reference to your viewControllers in an NSArray/NSSet and once you want a random viewController select a random index with:
arc4random();
Or if you don't want to init all the viewControllers at the start, you can create a set index to every viewController, and once the index is chosen you can init the matching viewController

Resources