views:

398

answers:

2

I read somewhere that in a programmatically created view in a UIViewController, not using Interface Builder, -viewDidLoad and -viewDidUnload should not be used. Is this right? Why? Where would I release subviews that I have retaining properties of? Or should I just not use properties for them?

EDIT: Read my comments on Rob Napier's answer.

+1  A: 

viewDidLoad and viewDidUnload are only called automatically for you if you use a NIB. If you're not using a NIB, then it's your responsibility to decide when to create and destroy your subviews. If you're doing it programmatically, you don't need what these methods provide (a hook for when the NIB loading system does it automatically).

You should be creating your subviews in loadView. You should be releasing things in dealloc, didReceiveMemoryWarning and viewWillDisappear. Of course, you have some flexibility here. If it's a particularly small view, or you need it a lot, you could choose to just release things in dealloc.

A good resource for best practices around when to allocate and release is Managing Memory Efficiently.

Rob Napier
`-viewDidUnload` is only called when using a NIB? Why does it say this in the documentation for `-didReceiveMemoryWarning`? "The default implementation of this method checks to see if the view controller can safely release its view. This is possible if the view itself does not have a superview and can be reloaded either from a nib file or using a custom loadView method. If the view can be released, this method releases it and calls the viewDidUnload method."
Mk12
Also, in the apple docs for `-loadView` it makes it seem like it is only for creating the view property, and it says this: "If you want to perform any additional initialization of your views, do so in the viewDidLoad method. In iPhone OS 3.0 and later, you should also override the viewDidUnload method to release any references to the view or its contents."
Mk12
I have an iphone Xcode project that doesn't use NIBS at all, yet both `-viewDidLoad` and `-viewDidUnload` get called in the UIViewControler subclasses. So your first statement must be wrong.
Mk12
Robs statement is totally wrong. -1 for that.
stigi
I can see how you don't really need `-viewDidLoad`, you could just use `-loadView`, but I do need to use `-viewDidUnload` programmatically so I might as well also use it's counterpart method.
Mk12
A: 

Create your subviews in -viewDidLoad. If you need ivars for them then only assign their values. The reference is hold by adding the views as subviews to you main view.

Then when your view is unloaded you should set your ivars to nil, because the object have been released since your view was removed and released.

So in your header

@interface MyViewController : UIViewController {
  IBOutlet UIView *someSubview; // assigned
}
@property (nonatomic, assign) IBOutlet UIView someSubview;
@end

And in your implementation

@implementation MyViewController
//... some important stuff

- (void)viewDidLoad;
{
  [super viewDidLoad];
  someSubview = [[UIView alloc] initWithFrame:self.view.bounds];
  [self.view addSubview:someSubview]; // retains someSubview
  [someSubview release];   // we don't hold it
}

- (void)viewDidUnload;
{
  [super viewDidUnload];
  someSubview = nil;  // set the pointer to nil because someSubview has been released
}

//... more important stuff

@end

If you wish you can also not release someSubview in -viewDidLoad, but then you have to release it in -viewDidUnload AND -dealloc since (if I remember right) -viewDidUnload isn't called before -dealloc. But this isn't necessary if you don't retain someSubview.

stigi
I think its more common to use retaining properties, but I'm not using Interface Builder so no IBOutlet. Usually I don't even use properties unless I need to expose the values, or if they are lazily-loaded. I understand the memory management and where to put what in which methods. Thanks for the answer.
Mk12
I know the view retains its subviews, but the general way to do it AFAIK is to use retaining properties, setting them to nil in -viewDidUnload, releasing in dealloc.
Mk12
Is there any official rule if IBOutlets are retained or assigned when set by nib loading when there's no property?
stigi
Well if you have no references to it in your code then its memory management wouldn't be your responsibility, but like I said I'm not using Interface Builder.
Mk12