Cómo llamar al método desde ViewController en GameScene

Tengo un método que tiene una transición personalizada en mi viewController que se ve así:

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

Llamo al método como tal en GameScene.swift:

  GameViewController().gameOver() 

Comprobé dos veces el nombre de transición y es correcto. Cada vez que llamo esto en mi archivo GameScene.swift obtengo el mensaje SIGABRT y no sé por qué. Intenté llamar a la función con solo un mensaje println () y funcionó.

Cualquier consejo sobre por qué ocurre esto y cómo puedo llamar al método exitosamente en el archivo GameScene.swift sería muy apreciado.

¡Gracias!

PD aquí está el registro de locking:

 2015-01-28 21:59:46.181 RunawaySquare[95616:3907041] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver () 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 

dice que no hay ID de segue con “GameEnd” pero hay uno y funciona si se usa en el viewcontroller

La razón por la que esto no funciona es porque estás creando una NUEVA instancia de GameViewController y luego estás llamando a gameOver sobre eso. Lo que realmente quieres hacer es hacer referencia a tu GameViewController existente

Hay algunas maneras de hacerlo, te daré un ejemplo.

agregue una propiedad viewController a su clase GameScene

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

en su archivo GameViewController

 // after GameScene is instantiated gameScene.viewController = self 

ahora tenemos una referencia a viewController, vamos a usarlo en nuestra clase GameScene

 // somewhere in GameScene self.viewController.gameOver() 

He hecho por crear protocolo, tengo 3 escenas de juego (GameScene, GamePlayScene, GameEndScene) y un controlador de juego (GameViewController)

primero crear juegoProtocolo

 protocol GameDelegate { func gameOver() } 

implementar protocolo en 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) } } 

poner propiedad de delegado en la clase GameScene

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

y poner el protocolo en GamePlayScene también

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

y, por último, poner propiedad de delegado y llamar a la función gameOver

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

Espero que funcione y pueda ayudarte

Atentamente, Donny

No sé si esto todavía es relevante, pero me gustaría presentarle una solución a este problema.

Como puede ver aquí Swift iOS: realizar un Segue desde una instancia en un ViewController a otro ViewController tuve el mismo problema hace algún tiempo, el cual pude arreglar usando Protocolos .

El problema es que puede llamar al “performSegueWithIdentifier (” GameOver “, sender: nil)” solo en su clase GameViewController, pero le gustaría ejecutarlo desde su Gamescene.

Por lo tanto, puedes crear en tu GameScene un protocolo como este:

 @objc protocol GameOverDelegate { func gameOverDelegateFunc() } 

y una variable para el delegado en el Gamescene:

 var gamescene_delegate : GameOverDelegate? 

en su clase GameViewController, debe agregar el delegado en la definición de la clase

 class GameViewController: UIViewController, GameOverDelegate { ... } 

y configure el delegado de la escena en la función viewDidLoad de su GameViewController en uno mismo:

 scene.gamescene_delegate = self 

El último paso es implementar la función gameOverDelegateFunc () en su GameViewController:

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

Esto es todo lo que tienes que hacer.

Cuando quiera realizar este Segue en su GameScene, solo tiene que llamar a la función a través del delegado de esta manera:

 gamescene_delegate?.gameOverDelegateFunc() 

Espero que todo esté claro y pueda ayudar,

Saludos, Phil

No tengo suficientes representantes para responder a tu último comentario, pero si sigues recibiendo ese error, es porque aún no has dado un nombre (o identificador) en Interface Builder.

Cuando hace clic y arrastra para dibujar los segmentos entre los controladores de vista en Interface Builder, puede seleccionar cada transición mediante el ícono de círculo que aparece en el centro de las líneas de transición y darle un ‘identificador’. Luego, cuando llame a performSegueWithIdentifier , ¡debería funcionar!

Así es como se vería el ícono circular, según el tipo de transición:

Icono Segue que le permite administrar propiedades segue

Si no estás seguro de los segues, ¡mira este tutorial o este !