2015-01-28 2 views
7

У меня есть метод, который имеет собственный SEGUE в моем ViewController который выглядит следующим образом:Как вызвать метод из ViewController в GameScene

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

я называю метод, как так в GameScene.swift:

GameViewController().gameOver() 

Я дважды проверял имя сегмента, и это правильно. Всякий раз, когда я называю это в своем файле GameScene.swift, я получаю сообщение SIGABRT, и я не знаю, почему. Я попытался вызвать функцию только с сообщением println(), и это сработало.

Любые советы о том, почему это происходит и как я могу успешно вызвать метод в файле GameScene.swift, будут с благодарностью оценены.

Спасибо!

P.S. вот аварийный журнал:

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 

В нем говорится, что нет идентификатора segue. с «GameEnd», но есть один, и он работает, если используется в viewcontroller

+0

Вы получаете любой отчет об ошибке на отладчике? –

+0

«завершение с неперехваченным исключением типа NSException» –

+0

Это обычное сообщение для вопросов с выходными соединениями и т. Д. –

ответ

24

Причина, по которой это не работает, заключается в том, что вы создаете новый экземпляр GameViewController, а затем вы вызываете gameOver. То, что вы действительно хотите сделать, это ссылка на существующий GameViewController

вот несколько способов сделать это, я приведу вам один пример.

добавить свойство ViewController к вашему GameScene класса

class GameScene { 

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

в файле GameViewController

// after GameScene is instantiated 
gameScene.viewController = self 

теперь у нас есть ссылка на ViewController, позволяет использовать его в нашем классе GameScene

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

Я пробовал это, но он по-прежнему дает аналогичное предупреждение, что «... не имеет segue с идентификатором GameEnd», который я не понимаю, так как я на 100% уверен, что это правильный идентификатор для пользовательского segue. Любые дальнейшие советы мне очень помогли, но спасибо вам все равно –

+2

Я знаю, что это было задано прикосновением более двух лет назад, но не могли бы вы описать чуть подробнее, где GameScene создается с вашей линией для gameScene.viewController = self? – Rocket6488

0

У меня недостаточно ответов, чтобы ответить на ваш последний комментарий, но если вы все еще получаете эту ошибку, это связано с тем, что вы еще не дали этому имени (или идентификатору) еще в интерфейсе Builder!

Когда вы нажимаете и перетаскиваете, чтобы рисовать сегменты между контроллерами представления в Interface Builder, вы можете выбрать каждый переход по значку круга, который отображается в центре линий segue, и дать ему «идентификатор». Затем, когда вы звоните performSegueWithIdentifier, он должен работать!

Это то, что круговой значок может выглядеть, в зависимости от типа Segue:

Segue icon that lets you manage segue properties

Если вы немного не уверены в перетекает, проверить this tutorial или this one!

1

Я не знаю, если это все еще актуально, но я хотел бы представить вам решение этой проблемы.

Как вы можете видеть здесь Swift iOS: Perform a Segue from an Instance in a ViewController to another ViewController У меня была такая же проблема некоторое время назад, что мне удалось исправить, используя Протоколы.

Проблема заключается в том, что вы можете вызвать «performSegueWithIdentifier (« GameOver », отправитель: nil)» только в вашем классе GameViewController, но вы хотели бы выполнить его с помощью вашей игры.

Therefor вы создаете в вашем GameScene протокол, как это:

@objc protocol GameOverDelegate { 
    func gameOverDelegateFunc() 
} 

и переменную для делегата в Gamescene:

var gamescene_delegate : GameOverDelegate? 

в вашем GameViewController класса вы должны добавить делегата определение класса

class GameViewController: UIViewController, GameOverDelegate { 
... 
} 

и установить делегат сцены в v Функция iewDidLoad вашего GameViewController к себе:

scene.gamescene_delegate = self 

Последний шаг заключается в реализации gameOverDelegateFunc() функцию в вашем GameViewController:

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

Это все, что вам нужно сделать.

Всякий раз, когда вы хотите, чтобы выполнить это SEGUE в вашем GameScene вы просто должны вызвать функцию через делегат, как это:

gamescene_delegate?.gameOverDelegateFunc() 

Я надеюсь, что все ясно, и я мог бы помочь,

С уважением , Фил

5

Я сделан создать протокол, у меня есть 3 сцены игры (GameScene, GamePlayScene, GameEndScene) и один игровой контроллер (GameViewController)

сначала создать gameProtocol

protocol GameDelegate { 
func gameOver() 
} 

реализации протокола в 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) 
} 
} 

положить делегат собственности в 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) 
    } 
} 

и поставить протокол в GamePlayScene слишком

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

и, наконец, поставил делегат свойство и вызвать функцию GameOver

class GameEndScene: SKScene { 
    var delegate: GameDelegate? 

    init(size: CGSize) { 
     // call gameOver function 
     self.delegate?.gameOver() 
    } 
    } 

Надеется, что работа и может помочь вам

С уважением, Донни

Смежные вопросы