简体   繁体   中英

error performing segue in Swift iOS

I've recently been playing around with swift segues and I'd love to incorporate one in my latest app, the problem is I can't seem to get them to work. So far I've created another view controller SecondViewController and referenced in my ViewController & SecondViewController files as so:

ViewController.swift

import UIKit

class ViewController: UIViewController {

var secondViewController: SecondViewController!
var viewController: ViewController!

override func viewDidLoad() {
//lots more code here

SecondViewController.swift

import UIKit

class SecondViewController: UIViewController {

var secondViewController: SecondViewController!
var viewController: ViewController!

override func viewDidLoad() {

Them in storyboard view I've crtl+dragged a segue from viewController to secondViewController and once that's been created given that segue an identifier using the right hand panel, the segue identifier is GameOver and the segue type is show .

Now I want to call the segue automatically with no interaction from the user, in the final app once the user hits the game over func it would trigger the segue and display a new UIView where the highscore could be displayed with a few other items.

The code I'm using to call the segue is:

self.viewController.performSegueWithIdentifier("GameOver", sender: self)

I receive the following error...

Thread 1:EXC_BAD_INSTRUCTION (code=EXC_1386_INVOP, subcode=0x0

I also have this error in the output field...

fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)

I've played around with the names of the segues and the file names and I still get the same error, I'm sure I'm missing something fundamental so hopefully someone can help me work this out.

I've created a new project and uploaded it to GitHub, if anyone could tell me what I'm missing that would be great, here is a link to my GitHub repository https://github.com/rich84ts/TestSingleView

Thank you.

You cannot just throw in some instance properties and expect them to magically do something:

class ViewController: UIViewController {

    var secondViewController: SecondViewController!
    var viewController: ViewController!

}

Those properties are nil , and sending a message to them will crash your app. You have to give them values .

In your case, the segue emanates from this view controller, so what you actually want to say is

self.performSegueWithIdentifier("GameOver", sender: self)

The other big mistake you are making is that you are saying all this in viewDidLoad . That is way too early! You can't do any segue-ing yet; your view is not even in the interface! Move your code into viewDidAppear: and it will actually work:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    self.performSegueWithIdentifier("GameOver", sender: self)
}

Your code is still silly and useless, but at least you will see something happen and you can continue developing from there.

What I actually recommend is that you delete your viewDidLoad implementation and put this:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    func delay(delay:Double, closure:()->()) {
        dispatch_after(
            dispatch_time(
                DISPATCH_TIME_NOW,
                Int64(delay * Double(NSEC_PER_SEC))
            ),
            dispatch_get_main_queue(), closure)
    }
    delay(1) {
        self.performSegueWithIdentifier("GameOver", sender: self)
    }
}

That will allow the first view controller to appear, wait one second, then summon the second view controller. And so you will learn that everything is hooked up correctly, and can proceed to do something more practical.

You can create a manual segue from the storyboard by control-clicking the ViewController object and dragging from the manual segue to the destination view controller. You can then call this segue with the designated identifier from your source controller. You don't need a reference to the destination view controller to achieve this.

To reference anything from the storyboard in your view controller you need to declare your properties like this:

@IBOutlet var someProperty : UIView?

The @IBOutlet bit makes the property visible on the storyboard and you can control-drag from it to a corresponding object in a view. You can't do this with view controllers though. To access the destination view controller in your source view controller before the segue you need to override func prepareForSegue(_ segue: UIStoryboardSegue, sender sender: AnyObject?) . This allows you to access the destination view controller from the segue-instance before the actual segue (if you need to pass it data for example).

Firstly your self.viewController is a nil object as you only created the variable and didn't initialize it. You can't call a method with nil object. Secondly you have created a push segue from storyboard but you don't have navigation controller in storyboard so self.performSegueWithIdentifier("GameOver", sender: self) will also not work. To use push segue you should have you current viewcontroller in UINavigationController's stack, so first add a UINavigationController in storyboard and make that initial view controller and set ViewController to the rootViewController of the navigation controller then call self.performSegueWithIdentifier("GameOver", sender: self)

Then the code will work. Hope this help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM