Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

-viewDidLoad not called in subclassed UIViewController

Have patience with me, I'm still learning Cocoa Touch. Other -viewDidLoad not being called question was unrelated to my issue, I did search.

I have FooViewController, a UIViewController subclass. FooViewController.xib has its File's Owner set to FooViewController. Additionally, I have Main, whose App Delegate is MyApplication and whose File's Owner is UIApplication. My primary nib is set to Main.

I am able to make the view appear on the screen, using this flow (code snipped for brevity):

UIWindow *main;

-(void)applicationDidFinishLaunching:(UIApplication*)application {
    [self showFooViewController];
    [main makeKeyAndVisible];
}

-(void)showFooViewController {
    fooViewController = [[FooViewController alloc] init];
    if(![[NSBundle mainBundle] loadNibNamed:@"FooViewController" owner:fooViewController options:nil]) {
        DebugF(@"Failed to load FooViewController");
        return;
    }

    // Add the view and put it in place
    UIView *view = [fooViewController view];
    CGRect cur = [view frame];
    cur.origin = CGPointMake(0.0f, 20.0f);
    [view setFrame:cur];

    [main addSubview:[fooViewController view]];
}

However, this message is not being sent to FooViewController:

- (void) viewDidLoad {
    DebugF(@"Hello!");
}

Total silence in gdb's output.

I've seen other Cocoa tutorials that show Instances and such in IB's document view, but I do not see these options in mine. Am I supposed to be instantiating fooViewController in the Nib? Did I miss a connection? In FooViewController.xib, File's Owner view is connected to the view in the Nib.

I'm sure this is a simple solution, and I have wandered down the wrong path. Halp!

like image 295
Jed Smith Avatar asked Sep 25 '09 21:09

Jed Smith


3 Answers

And I've answered my own question, so this may help future folks. Since I see viewDidLoad has, as its three top Googles in my suggest, "viewDidLoad not called", "viewDidLoad not getting called", and "viewDidLoad not firing", I imagine this is a usual mistake...

Changing:

fooViewController = [[FooViewController alloc] init];
if(![[NSBundle mainBundle] loadNibNamed:@"FooViewController" owner:fooViewController options:nil]) {
    DebugF(@"Failed to load FooViewController");
    return;
}

To:

fooViewController = [[FooViewController alloc] initWithNibName:@"FooViewController" bundle:[NSBundle mainBundle]];

Fixed the problem. Obviously a mistake in how I'm using Cocoa.

like image 94
Jed Smith Avatar answered Nov 03 '22 02:11

Jed Smith


I have not found documentation to back up the following, but this is what I've deduced by experiment / experience:

The viewDidLoad method is expected be called immediately after loadView is called, and it's up to whomever calls loadView to supply the extra call to viewDidLoad.

In some cases, the SDK will handle this behavior for you. Suppose you have a subclass of UIViewController called MyViewController; then:

  • If you access myViewController.view before you call loadView, then the superclass accessor is smart enough to call loadView for you, and viewDidLoad immediately thereafter.

As a result, if your code looks like this:

MyViewController *myViewController = [[MyViewController alloc] init];
[superView addSubview:myViewController.view];  // Calls viewDidLoad.

then both loadView and viewDidLoad will be called on your behalf.

However, if your code looks like this:

MyViewController *myViewController = [[MyViewController alloc] init];
[myViewController loadView];
[superView addSubview:myViewController.view];  // Doesn't call viewDidLoad.

then the view getter can see you've already loaded the view, and it assumes you also called viewDidLoad as well - so it doesn't call either. Ironically, the extra function call here prevents viewDidLoad from getting called.

like image 23
Tyler Avatar answered Nov 03 '22 02:11

Tyler


I have had this same problem twice. The first time, I forgot to connect the view of UITableViewController to the actual UITableView in interface builder. The second time, I forgot to make awakeFromNib call itself in the superclass.

like image 30
Casebash Avatar answered Nov 03 '22 01:11

Casebash