3
votes

I've tried seating SO and Google but it seems no one has had this issue.

I have two ViewControllers in my iOS app.

In viewControllerA on a tap event I call:

[self performSegueWithIdentifier:@"fooSegue" sender:self];

Which this calls:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

on viewControllerA

No problem there.

However after that method,

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

is called on viewControllerB before viewDidLoad is even called. I don't need this mothod to run on this viewController at this stage. Along with that, viewDidLoad / viewWillApear are called twice after the prepareForSegue has been called on viewControllerB

I tried doing a stack strace to see who is calling it - but this is what I got:

* thread #1: tid = 0x5eac3, 0x0001e859 TestApp`-[viewControllerB prepareForSegue:sender:](self=0x0dad98b0, _cmd=0x0188185a, segue=0x0ce9e6f0, sender=0x0dad98b0) + 89 at viewControllerB.m:444, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1   * frame #0: 0x0001e859 TestApp`-[ViewControllerB prepareForSegue:sender:](self=0x0dad98b0, _cmd=0x0188185a, segue=0x0ce9e6f0, sender=0x0dad98b0) + 89 at ViewControllerB.m:444
    frame #1: 0x015f8efa UIKit`-[UIStoryboardSegueTemplate _perform:] + 156
    frame #2: 0x015f8f87 UIKit`-[UIStoryboardSegueTemplate perform:] + 115
    frame #3: 0x011b32e2 UIKit`-[UIViewController loadViewIfRequired] + 605
    frame #4: 0x011b35d9 UIKit`-[UIViewController view] + 35
    frame #5: 0x011cd942 UIKit`-[UINavigationController _startCustomTransition:] + 778
    frame #6: 0x011da8f7 UIKit`-[UINavigationController _startDeferredTransitionIfNeeded:] + 688
    frame #7: 0x011db4e9 UIKit`-[UINavigationController __viewWillLayoutSubviews] + 57
    frame #8: 0x0131c0d1 UIKit`-[UILayoutContainerView layoutSubviews] + 213
    frame #9: 0x01103964 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355
    frame #10: 0x023e682b libobjc.A.dylib`-[NSObject performSelector:withObject:] + 70
    frame #11: 0x0286245a QuartzCore`-[CALayer layoutSublayers] + 148
    frame #12: 0x02856244 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 380
    frame #13: 0x028560b0 QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 26
    frame #14: 0x027bc7fa QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 294
    frame #15: 0x027bdb85 QuartzCore`CA::Transaction::commit() + 393
    frame #16: 0x0287b5b0 QuartzCore`+[CATransaction flush] + 52
    frame #17: 0x010929bb UIKit`_UIApplicationHandleEventQueue + 13095
    frame #18: 0x02a1e77f CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
+ 15
    frame #19: 0x02a1e10b CoreFoundation`__CFRunLoopDoSources0 + 235
    frame #20: 0x02a3b1ae CoreFoundation`__CFRunLoopRun + 910
    frame #21: 0x02a3a9d3 CoreFoundation`CFRunLoopRunSpecific + 467
    frame #22: 0x02a3a7eb CoreFoundation`CFRunLoopRunInMode + 123
    frame #23: 0x04bca5ee GraphicsServices`GSEventRunModal + 192
    frame #24: 0x04bca42b GraphicsServices`GSEventRun + 104
    frame #25: 0x01094f9b UIKit`UIApplicationMain + 1225    
    frame #26: 0x0011112d TestApp`main(argc=1, argv=0xbfffedf8) + 141 at main.m:16

I'm not sure what to make of this.

Can anyone asset with whats going on here?

1
Do you have a container view on the destination view controller's view? Container views have an embed segue (giving your parent view controller a chance to pass whatever the child view controller needs, if anything.Rob
Actually, yes it does! Do I need to do something to stop the viewDidLoad and viewWillAppear being called multiple times?Robert J. Clegg
You should see viewDidLoad/viewDidAppear/etc. called on the destination view controller (the parent view controller) and then again on its child view controller (that embedded view's view controller). You want different view controllers for the parent and child view controller, and each should see their own series of calls).Rob
Thank you. This really helps! Please mark your comments as an answer and I will accept them!Robert J. Clegg

1 Answers

7
votes

If the destination scene has a "container view" that you added via Interface Builder, that includes an embed segue, which is automatically called when you transition to the parent view controller. This segue will trigger the instantiation of the child view controller and its view(s) and this process ends up calling prepareForSegue on the parent view controller, giving it a chance to pass whatever information the child view controller might need (if anything).

You should see viewDidLoad, viewDidAppear, etc., to be called on the destination's parent view controller, as well as on the child view controller.