gklka
gklka

Reputation: 2574

Waiting the finish of instantiateViewControllerWithIdentifier

I have a Storyboard and instantiate a view controller from code like this:

NSLog(@"1");
MyController *vc = (MyController *)[[UIStoryboard storyBoardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"MyController"];
NSLog(@"4");

The implementation of the MyController class includes the following:

- (void)viewDidLoad {
    NSLog(@"2");
    [super viewDidLoad];
    [NSThread sleepForTimeInterval:2];
    NSLog(@"3");
}

I expect to see the following output when I run my code:

1
2
3
4

But it seems that -viewDidLoad is not even called until I access MyController's view:

1
4

If I modify the first like this:

NSLog(@"1");
MyController *vc = (MyController *)[[UIStoryboard storyBoardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"MyController"];
[vc view]; // Just accessing
NSLog(@"4");

Then it the output will be:

1
4
2
3

How can I be sure that my properties are initialized (-viewDidLoad ran) and I can give parameters to my controller? What is the recommended way to do this?

Upvotes: 3

Views: 155

Answers (2)

Avi
Avi

Reputation: 7552

You should write your VC such that it doesn't matter if the view is loaded before or after properties are set.

If you have a property like this:

@property (nonatomic, copy) NSString *superAwesomeLabelText;

And you need to set the text of your super-awesome label, have the following:

In viewDidLoad

self.superAwesomeLabel.text = (self.superAwesomeLabelText) ?: @"Default lame text";

The setter for superAwesomeLabelText:

- (void)setSuperAwesomeLabelText:(NSString*)superAwesomeLabelText {
    _superAwesomeLabelText = [superAwesomeLabelText copy];

   self.superAwesomeLabel.text = superAwesomeLabelText;
}

Now it doesn't matter whether the view is loaded before or after the property is set.

Upvotes: 1

Vitalii Gozhenko
Vitalii Gozhenko

Reputation: 9354

This is because viewDidLoad called only after you present view controller modally or push to navigation controller, or display it somehow. So if you want to receive 1,2,3,4, you need something like this:

NSLog(@"1");
MyController *vc = (MyController *)[[UIStoryboard storyBoardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"MyController"];
[self presentViewController:vc animated:YES completion:^{
    NSLog(@"4");
}];

Upvotes: 1

Related Questions