segue: destination view controller weirdness

TotoroTotoro picture TotoroTotoro · Jun 2, 2012 · Viewed 21k times · Source

In my app, I use a storyboard and segues, and I often pass data to the destination view controller before doing the segue, as follows:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{
    if ([segue.destinationViewController respondsToSelector:@selector(setMyData:)]) {
        [segue.destinationViewController performSelector:@selector(setMyData:) 
                                          withObject:myData];
    }
} 

It works everywhere except in one place. The selector gets called, the data gets set, but when the segue completes and the destination controller appears, it doesn't have the data I just set. After printing the view controller's id in both the source and destination view controllers, I found that the segue.destinationViewController in the code above is a DIFFERENT instance of the view controller than the one that gets displayed. What's going on here?

[UPDATE 1] I looked into the lifecycle of the destination view controller, and it first gets loaded during the segue execution, but AFTER I set the property on it! This means, that when I call performSelector on it, the view controller object is not initialized! This is why the data I set doesn't stick. t don't understand why is this the case, and why this same approach works in the other parts of my app.

[UPDATE 2] Posting the code of setMyData by request. At first I didn't have this method at all, because locationToOpen is a public property. I only added it to ensure it gets called and to print the debug info.

- (void)setMyData:(MyData *)myData
{
    DLog(@"self: %@", (id)self);
    _myData = myData;
}

Answer

Arunabh Das picture Arunabh Das · Dec 26, 2012

I would do it as follows -

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{
    if ([segue.identifier isEqualToString:@"NextSegue"]) 
    {
        DestinationViewController *dest = [segue destinationViewController];

        dest.myData = self.myData; 
    }
}

And in the DestinationViewController.h, you should create a property -

#import <UIKit/UIKit.h>

@interface DestinationViewController : UIViewController

@property (nonatomic, strong) NSObject *myData;


@end

And also, make sure to synthesize the myData property in DestinationViewController.m -

@interface DestinationViewController ()

@end

@implementation DestinationViewController

@synthesize myData = _myData;

// other methods here

@end