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!
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.
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:
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With