views:

10070

answers:

3

When working with views and view controllers in an iPhone app, can anyone explain the difference between loadView and viewDidLoad?

My personal context, is that I build all my views from code, I do not and will not use Interface Builder, should that make any difference.

I've found that often when I add init code to loadView, I end up with an infinite stack trace, so I typically do all my child-view building in viewDidLoad...but it's really unclear to me when each gets executed, and what is the more appropriate place to put init code. What would be perfect, is a simple diagram of the initialization calls.

Thanks!

+5  A: 

loadView is the method in UIViewController that will actually load up the view and assign it to the "view" property. This is also the location that a subclass of UIViewController would override if you wanted to programatically set up the "view" property.

viewDidLoad is the method that is called once the view has been loaded. This is called after loadView is called. It is a place where you can override and insert code that does further initial setup of the view once it has been loaded.

NilObject
+2  A: 

Just adding some code examples to demonstrate what NilObject said:

- (void)loadView
{
    // create and configure the table view
    myTableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStyleGrouped]; 
    myTableView.delegate = self;
    myTableView.dataSource = self;
    myTableView.scrollEnabled = NO;
    self.view = myTableView;

    self.view.autoresizesSubviews = YES;
}

- (void)viewDidLoad 
{
  self.title = @"Create group";

  // Right menu bar button is to Save
  UIBarButtonItem *saveButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Save" style:UIBarButtonItemStyleDone target:self action:@selector(save)];
  self.navigationItem.rightBarButtonItem = saveButtonItem;
  [saveButtonItem release];
}
alamodey
so, between the two of you, is it accurate to say that loadView is where I should do the alloc/init of my controller's self.view, and child views should be handled in viewDidLoad (or later)?
ryan.scott
+33  A: 

I can guess what might be the problem here, because I've done it:

I've found that often when I add init code to loadView, I end up with an infinite stack trace

Don't read self.view in -loadView. Only set it, don't get it.

The self.view property accessor calls -loadView if the view isn't currently loaded. There's your infinite recursion.

The usual way to build the view programmatically in -loadView, as demonstrated in Apple's pre-Interface-Builder examples, is more like this:

UIView *view = [[UIView alloc] init...];
...
[view addSubview:whatever];
[view addSubview:whatever2];
...
self.view = view;
[view release];

And I don't blame you for not using IB. I've stuck with this method for all of Instapaper and find myself much more comfortable with it than dealing with IB's complexities, interface quirks, and unexpected behind-the-scenes behavior.

Marco
ahhhh, thank you for an explanation, finally! I've shied away from the idiom of allocating a temporary variable, then setting to self.view, then releasing...it seemed somehow awkward, unnecessary. I can now understand why that decision would have led me down the path where I now find myself.
ryan.scott