How to call method from ViewController in GameScene
Solution 1
the reason this doesnt work is that you are creating a NEW instance of GameViewController
and then you're calling gameOver
on that. What you really want to do is reference your existing GameViewController
theres a few ways to do this, I'll give you one example.
add a viewController property to your GameScene class
class GameScene {
// we need to make sure to set this when we create our GameScene
var viewController: GameViewController!
in your GameViewController file
// after GameScene is instantiated
gameScene.viewController = self
now we have a reference to viewController, lets use it in our GameScene class
// somewhere in GameScene
self.viewController.gameOver()
Solution 2
I have done by create protocol, I have 3 game scene (GameScene, GamePlayScene, GameEndScene) and one game controller (GameViewController)
first create gameProtocol
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 delegate property in 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 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 last, put delegate property and call gameOver function
class GameEndScene: SKScene {
var delegate: GameDelegate?
init(size: CGSize) {
// call gameOver function
self.delegate?.gameOver()
}
}
Hope that work and can help you
Sincerely, Donny
Solution 3
I don't know if this is still relevant, but I would like to present you a solution to this problem.
As you can see here Swift iOS: Perform a Segue from an Instance in a ViewController to another ViewController I had the exact same problem some time ago, which I managed to fix using Protocols.
The problem is, that you can call the "performSegueWithIdentifier("GameOver", sender: nil)" only in your GameViewController Class, but you would like to execute it from your Gamescene.
Therefor you create in your GameScene a protocol like this:
@objc protocol GameOverDelegate {
func gameOverDelegateFunc()
}
and a variable for the delegate in the Gamescene:
var gamescene_delegate : GameOverDelegate?
in your GameViewController Class you have to add the delegate in the class definition
class GameViewController: UIViewController, GameOverDelegate {
...
}
and set the delegate of the scene in the viewDidLoad function of your GameViewController to self:
scene.gamescene_delegate = self
The last step is to implement the gameOverDelegateFunc() function in your GameViewController:
func gameOverDelegateFunc() {
self.performSegueWithIdentifier("GameOver", sender: nil)
}
This is all you have to do.
Whenever you want to perform this Segue in your GameScene you just have to call the function through the delegate like this:
gamescene_delegate?.gameOverDelegateFunc()
I hope that everything is clear and I could help,
Regards, Phil
Jonathan H.
Updated on July 21, 2022Comments
-
Jonathan H. almost 2 years
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 like so in GameScene.swift:
GameViewController().gameOver()
I double checked the segue name and it is correct. Whenever I call this in my GameScene.swift file I get the SIGABRT message and I don't know why. I tried calling the function with only a println() message and it worked.
Any advice on why this is occurring and how I can successfully call the method in the GameScene.swift file would be greatly appreciated.
Thanks!
P.S. 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
it says there is no segue id. with "GameEnd" but there is one and it works if used on the viewcontroller