How to call a method from ViewController in GameScene

I have a method that has a custom segue in my viewController that looks like this:

func gameOver() { performSegueWithIdentifier("GameOver", sender: nil) } 

I call the method, as in GameScene.swift:

  GameViewController().gameOver() 

I double checked the name of segue and it is correct. Whenever I call it in my GameScene.swift file, I get a SIGABRT message and I don't know why. I tried calling the function only with the message println (), and it worked.

Any advice on why this is happening and how I can successfully call the method in the GameScene.swift file would be greatly appreciated.

Thanks!

PS here is the crash log:

 2015-01-28 21:59:46.181 RunawaySquare[95616:3907041] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver (<RunawaySquare.GameViewController: 0x7fe4305c7890>) has no segue with identifier 'GameEnd'' *** First throw call stack: ( 0 CoreFoundation 0x000000010d461f35 __exceptionPreprocess + 165 1 libobjc.A.dylib 0x000000010f39ebb7 objc_exception_throw + 45 2 UIKit 0x000000010e20dd3b -[UIViewController shouldPerformSegueWithIdentifier:sender:] + 0 3 RunawaySquare 0x000000010d2683b2 _TFC13RunawaySquare18GameViewController8gameOverfS0_FT_T_ + 914 4 RunawaySquare 0x000000010d261af0 _TFC13RunawaySquare9GameScene12touchesBeganfS0_FTCSo5NSSet9withEventCSo7UIEvent_T_ + 1808 5 RunawaySquare 0x000000010d261c3f _TToFC13RunawaySquare9GameScene12touchesBeganfS0_FTCSo5NSSet9withEventCSo7UIEvent_T_ + 79 6 SpriteKit 0x000000010df4d7e1 -[SKView touchesBegan:withEvent:] + 946 7 UIKit 0x000000010e12d16e -[UIWindow _sendTouchesForEvent:] + 325 8 UIKit 0x000000010e12dc33 -[UIWindow sendEvent:] + 683 9 UIKit 0x000000010e0fa9b1 -[UIApplication sendEvent:] + 246 10 UIKit 0x000000010e107a7d _UIApplicationHandleEventFromQueueEvent + 17370 11 UIKit 0x000000010e0e3103 _UIApplicationHandleEventQueue + 1961 12 CoreFoundation 0x000000010d397551 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17 13 CoreFoundation 0x000000010d38d41d __CFRunLoopDoSources0 + 269 14 CoreFoundation 0x000000010d38ca54 __CFRunLoopRun + 868 15 CoreFoundation 0x000000010d38c486 CFRunLoopRunSpecific + 470 16 GraphicsServices 0x000000011480e9f0 GSEventRunModal + 161 17 UIKit 0x000000010e0e6420 UIApplicationMain + 1282 18 RunawaySquare 0x000000010d26cbee top_level_code + 78 19 RunawaySquare 0x000000010d26cc2a main + 42 20 libdyld.dylib 0x000000010fb8a145 start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException 

he says there is no segue id. with "GameEnd", but there is one, and it works if used in the viewcontroller

+7
ios uiviewcontroller swift sprite-kit skscene
source share
4 answers

the reason this doesn't work is because you create a NEW instance of GameViewController and then you call gameOver . What you really want to do is link to an existing GameViewController

Here are some ways to do this, I will give you one example.

add viewController property to GameScene class

 class GameScene { // we need to make sure to set this when we create our GameScene var viewController: GameViewController! 

in the file GameViewController

 // after GameScene is instantiated gameScene.viewController = self 

now we have a link to viewController, you can use it in our GameScene class

 // somewhere in GameScene self.viewController.gameOver() 
+24
source share

I did by creating a protocol, I have 3 game scenes (GameScene, GamePlayScene, GameEndScene) and one game controller (GameViewController)

create gameProtocol first

 protocol GameDelegate { func gameOver() } 

implement protocol in GameViewController

 class GameViewController: UIViewController, GameDelegate { override func viewDidLoad() { super.viewDidLoad() let scene = GameScene(size: skView.bounds.size) scene.scaleMode = .AspectFill scene.delegate = self } // MARK: Game Delegate func gameOver() { self.performSegueWithIdentifier("yoursegue", sender: self) } } 

Put the delegate property in the GameScene class

 class GameScene: SKScene { var delegate: GameDelegate? // call GamePlayScene and put delegate property func redirectToPlay() { let transition = SKTransition.pushWithDirection(SKTransitionDirection.Left, duration: 1.0) let menuScene = GamePlayScene(size: size) menuScene.delegate = self.delegate self.view?.presentScene(menuScene, transition: transition) } } 

and put the protocol in GamePlayScene too

 class GamePlayScene: SKScene { var delegate: GameDelegate? // call GameEndScene and put delegate property func gameScore() { let transition = SKTransition.pushWithDirection(SKTransitionDirection.Left, duration: 1.0) let menuScene = GameEndScene(size: size) menuScene.delegate = self.delegate self.view?.presentScene(menuScene, transition: transition) } } 

and finally set the delegate property and call the gameOver function

 class GameEndScene: SKScene { var delegate: GameDelegate? init(size: CGSize) { // call gameOver function self.delegate?.gameOver() } } 

Hope this helps you and helps you.

Regards, Donnie

+5
source share

I do not know if this is really relevant, but I would like to present you a solution to this problem.

As you can see here Swift iOS: execute Segue from an instance in the ViewController to another ViewController I had the same problem some time ago that I managed to fix using Protocols .

The problem is that you can only call "performSegueWithIdentifier (" GameOver ", sender: nil) in your GameViewController class, but you would like to execute it from your game.

Therefore, you create the following protocol in your GameScene:

 @objc protocol GameOverDelegate { func gameOverDelegateFunc() } 

and the variable for the delegate in Gamescene:

 var gamescene_delegate : GameOverDelegate? 

in your GameViewController class you need to add a delegate to the class definition

 class GameViewController: UIViewController, GameOverDelegate { ... } 

and set the scene delegate to the viewDidLoad function of your GameViewController for yourself:

 scene.gamescene_delegate = self 

The final step is to implement the gameOverDelegateFunc () function in your GameViewController:

 func gameOverDelegateFunc() { self.performSegueWithIdentifier("GameOver", sender: nil) } 

That is all you have to do.

Whenever you want to execute this Segue in your GameScene, you just need to call the function through the delegate as follows:

 gamescene_delegate?.gameOverDelegateFunc() 

I hope everything is clear, and I could help,

Regards, Phil

+1
source share

I do not have enough answers to answer your last comment, but if you still get this error, it is because you have not yet given this segment a name (or identifier) ​​in Interface Builder!

When you click and drag to draw segments between view controllers in Interface Builder, you can select each transition by the circle icon that appears in the center of the segue lines and give it an β€œidentifier”. Then when you call performSegueWithIdentifier , it should work!

Here's what the circular icon looks like depending on the type of segue:

Segue icon that lets you manage segue properties

If you're a little unsure of segues, check out this tutorial or this

0
source share

All Articles