wuntee
wuntee

Reputation: 12490

iOS Modal Segue drops source ViewController?

When doing a modal segue, does the originating ViewController get discarded after the segue is performed? I am setting the destination controller's delegate to the source ViewController, but when the destination ViewController.viewDidLoad, the self.delegate is nil...

The following code will produce the log message "ListViewController.viewDidLoad: My delegate is nil :("

[Source] MapViewController:

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    if([segue.identifier isEqualToString:@"mapToList"]){
        NSLog(@"MapViewController.prepareForSegue: Segue mapToList being called, setting LisViewController's delegate to myself");
        [segue.destinationViewController setDelegate:self];
        if(!self){
            NSLog(@"MapViewController.prepareForSegue: I am nil.");
        } else {
            NSLog(@"MapViewController.prepareForSegue: I am NOT nil.");
        }
    }
}

[Destination] ListViewController:

- (void)viewDidLoad
{
    [super viewDidLoad];

    if(!self.delegate){
        NSLog(@"ListViewController.viewDidLoad: My delegate is nil :(");
    } else {
        NSLog(@"ListViewController.viewDidLoad: My delegate populated");
    }
}

Upvotes: 2

Views: 2658

Answers (3)

jkratz
jkratz

Reputation: 393

This is an old question but I came upon it when running into the same issue myself. Couple of things here:

  1. To the guy who didn't understand why someone would want to use a Nav controller with a modal display - its to get the benefit of the nav bar without having to embed a UINavigationBar into your own view controller like tw airball did.
  2. To solve the problem without resorting to what tw airball did remember that the destination view controller for the segue in this case is the navigation controller...not the view controller embedded in the nav.

So the fix is in your prepareForSeque:

UINavigationController *navController = segue.destinationViewController;
MyRealDestViewController *myRealDestViewController = (MyRealDestViewController)navController.topViewController;
myRealDestViewController.delegate = self;

Upvotes: 3

tw airball
tw airball

Reputation: 1359

If the segue is to a NavigationController then the destinationViewController loses the delegate.

I got around this problem by having the modal segue into the destinationViewController, and then adding NavigationBar and Bar Buttons to simulate the navigation controller (I assume you wrapped the destinationViewController in a NavigationController for the "done" and "cancel" buttons).

Set the delegate as normal in the rootViewController:

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

   if ([segue.identifier isEqualToString:@"segueToModalView"]){
     [segue.destinationViewController setDelegate:self];  
   }
}

Hope that helps

Upvotes: 1

Mike Z
Mike Z

Reputation: 4111

Your code seems correct, the only thing I have done differently is test this in a skeleton framework I have that is a tableviewcontroller nested in a navigationcontroller. I just tested with the following code and it works fine for me:

RootViewController .h:

@interface RootTableViewController : UITableViewController <newTest>

Prepare for Segue (in rootViewController):

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

 if ([segue.identifier isEqualToString:@"segueToModalView"]){
       [segue.destinationViewController setDelegate:self];  
 }
}

Top of Modal View Controller .h:

@protocol newTest <NSObject>
  -(void) hello;
@end

Property Declaration in Modal View:

@property (nonatomic, strong) id <newTest> delegate;

ViewDidLoad in Modal View:

- (void)viewDidLoad
{
   [super viewDidLoad];
   NSLog(@"%@", self.delegate);
}

My NSLog of self.delegate properly prints out and my code appears to be more or less the same as yours. Is your property declared correctly?

Upvotes: 3

Related Questions