28

Based on the Stanford iOS course I am playing with modal view controllers. In the demo they have a button that would launch a modal view and when it is clicked the function prepareForSegue is called. I mimicked the code and implementation into my project with the only difference is that my demo is on an iPhone storyboard and theirs is on the iPad.

I noticed that while my modal view controller is coming up, it does not call prepareForSegue prior to that. I searched the Stanford project to see where they may register any segue behavior before prepareForSegue is called but there is no evidence. Can anyone shed some light on this. I searched stack overflow and all I found were that users were missing the call implementation of performSegueWithIdentifier. However, in the Stanford demo they never do that.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier hasPrefix:@"Create Label"]) {
        AskerViewController *asker = (AskerViewController *)segue.destinationViewController;
        asker.question = @"What do you want your label to say?";
        asker.answer = @"Label Text";
        asker.delegate = self;
    }

}

Here is an example of there storyboard: enter image description here

Here is an example of my storyboard: enter image description here

In the debugger when I stop in the Stanford Demo code the call stack shows that the storyboard is performing a segue action, what do I need to configure in my storyboard to achieve the same result? enter image description here

Amro Younes
  • 1,261
  • 2
  • 16
  • 34
  • 1
    How do you know `prepareForSegue:` is not being called? I bet it is being called. The only way to be sure is to put a breakpoint on the very first statement in it. Have you done that? – matt Feb 07 '14 at 04:29
  • 1
    Yes I have, that is why I am asking the question. In my demo, my prepreForSegue is not being called, but in the Stanford demo it is. – Amro Younes Feb 07 '14 at 04:48

10 Answers10

35

Well, as it turns out, my view controller where button calls the modal view did not have the right class where prepareForSegue is implemented. It was the default UIViewController instead of my custom class.

The way I figured it out was by putting a break point in viewDidLoad and even that was not breaking and thus I suspected that in the storyboard I did not have the right class associated with the view where the button is implemented.

Amro Younes
  • 1,261
  • 2
  • 16
  • 34
  • 12
    Well done. And you learned something important! This is an easy mistake to make and you'll make it many more times. :)))) – matt Feb 07 '14 at 05:01
  • I hate to admit it, I have made this mistake before. I can't believe it took me a while to figure this one out! – Amro Younes Feb 07 '14 at 05:21
15

For others with this problem, if you are now using Swift 3 having the following function will not throw errors as it is the correct syntax but it will not work because it is the Swift 2 function:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    // code
}

You must update to Swift 3 "prepare" function for it to work for segues:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // code
}
Manuel BM
  • 868
  • 1
  • 13
  • 17
  • 1
    Some kind of warning or error by Apple would have helped when Swift 2 methods are not compatible and behave indifferently in Swift 3. Unfortunately thats not the case, thanks for the answer, it worked – Naishta Sep 02 '17 at 20:21
  • Thanks! Most helpful +1 – ICL1901 Feb 11 '18 at 17:13
11

When hooking up an automatic segue for a table view, there is, in addition to Amro's answer (not assigning your corresponding subclass), another two cases where prepareForSegue might not be called. Ensure you've:

  1. hooked up the segue from the table view prototype cell, not the table view controller.

  2. used a segue from under the "Selection Segue" group in the segue connection pop-up menu, not one under "Accessory Action".

Hooking up automatic segues

[Click image to enlarge]

uɥƃnɐʌuop
  • 14,022
  • 5
  • 58
  • 61
  • FWIW the accessory action is about `ⓘ` or `﹥`, etc. for more see http://www.imaladec.com/upload-files/images/Examples/TableView/DetailsCellsTableView/DetailsCells_01.jpg – mfaani Sep 25 '19 at 11:56
5

Whether its an Modal or Push Segue below code will always be called

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"Create Label"]) {
        SignUpViewController *asker = segue.destinationViewController;
    }
}
klefevre
  • 8,595
  • 7
  • 42
  • 71
bhavya kothari
  • 7,484
  • 4
  • 27
  • 53
2

I had a similar problem with UICollectionViewCell as the source of segue.
It seems that for the storyboard segue to work (without performSegueWithIdentifier) it's required that you have a custom subclass of UICollectionViewCell, and use it as a Class for the CollectionViewCell on the story board.

Adam Silenko
  • 3,025
  • 1
  • 14
  • 30
2

I had a similar issue.

The thought process was:

  1. make sure you have the correct method signature. It has changed in Swift 3.
  2. Then make sure the way you have hooked up the button (or whatever that triggers the segue) matches with the way you have hooked the segue in storyboard. Sometimes you call a button, but haven't properly hooked up the segue from that button to the destination viewcontroller.
  3. Be sure the identifier of the segue is correct. Though this isn't the reason the prepareForSegue doesn't get called, this only the reason that a specific segue isn't called.
mfaani
  • 33,269
  • 19
  • 164
  • 293
2

In my case, it ocured because my controller was extending another controller (Eureka Form View Controller = FormViewController) witch has implemented the performSegue function like this:

open override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // code
}

My function was implemented like this:

func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // code
}

To solve this, i just added override before:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // code
}

Voila!

Vincent Guyard
  • 405
  • 4
  • 11
1

In my case, I did not set the module under the name of the class in the storyboard of the view controller that contains the segue. It was set to none and once I clicked in the module field it set to the correct project / module and resolved the issue.

Logan Sease
  • 372
  • 3
  • 5
0

In my case, I have a base class for several view controllers in my project. That base class has an implementation of prepareForSegue() which wasn't getting called in every case. The problem was that in one of my view controllers that inherits from the base class and overrides its prepareForSegue() implementation, I forgot to call super.prepareForSegue().

ClayJ
  • 377
  • 2
  • 14
-1

Firstly you have to select on your button + ctrl drag item to you view controller choose selection segue .Later, you have to name segue identifier properly.

Don't connect to one view controller to other view controller. import UIKit.framework for this Then this method will get called.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"identifierName"])
    {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        ExampleViewController *destViewController = segue.destinationViewController;
    }
}
Dan Beaulieu
  • 19,406
  • 19
  • 101
  • 135
Nagarjun
  • 6,557
  • 5
  • 33
  • 51