1
votes

I have a quick question about the dealloc() and viewDidUnload() methods. I notice a lot of code examples, people seem to do different things.

Also, I might add that ARC is not an option.

(1) Should I set all the properties to nil in the dealloc() method including IBOutlets. For example, should I release the instance variable [_myArrary release] and also set self.myArrary = nil.

(2) In viewDidUnload, I think I must set all IBOutlets to nil, and also anything that is created in viewDidLoad. However, what about myString, lets say it is intialized in another method after viewDidLoad is called. Should I set that to nil?

If I have some properties declared as such:

@property (nonatomic, retain) IBOutlet UITableViewCell *myTableCell;
@property (nonatomic, retain) IBOutlet UILabel *myLabel;
@property (nonatomic, retain) NSArray *myArrary;
@property (nonatomic, retain) NSString *myString;

I synthesize them as such:

@synthesize myArrary = _myArrary;
@synthesize myTableCell;
@synthesize myLabel;
@synthesize myString;

- (void)viewDidLoad
{
    [super viewDidLoad];

    _myArrary = [NSArrary alloc] initWithObjects:@"testObject", nil];
}

- (void)viewDidUnload
{
    self.myArrary = nil;

    self.myTableCell = nil;

    self.myLabel = nil;

    [super viewDidUnload];
}

- (void)dealloc
{   
    [_myArray release];

    [super dealloc];
}
2

2 Answers

4
votes
  1. It shouldn't matter if you set the properties/variables to nil in dealloc because once the object is deallocated you won't be able to access them anyway. With retain properties, doing

    self.varname = nil;

    will both release the variable and set it to nil. A lot of people prefer to only release them, I prefer to set retain properties to nil for consistency.

  2. In viewDidUnload you should release and set to nil anything that is unneeded and that will be recreated when the view loads again. This is not a strict rule, but good practice to keep as much memory available as possible. If your string will be recreated in viewDidLoad and you won't need to access it until the view is loaded again, then you should probably release it (and I would set it to nil for safety).

    Another note, viewDidUnload does not always get called before dealloc. So you should be releasing every property/variable is dealloc, even if it is also released and set to nil in viewDidUnload. In order to make sure you won't leak when your class is deallocated, your dealloc function for that code should look like this:

    - (void)dealloc {
        [myTableCell release];
        [myLabel release];
        [_myArray release];
        [myString release];
    
        [super dealloc];
    }
    

    Setting them to nil is also acceptable, but only if you use the synthesized setter, because this also releases the variable.

    self.myLabel =  nil;
    

    is fine, but

    myLabel = nil;
    

    is leaky.

2
votes

In general, you want your viewDidUnload to release anything that can be recreated in viewDidLoad if your ViewController has not been dealloced in the meantime.

In dealloc, you need to release anything that the ViewController still owns. You can't assume that viewDidUnload was called first, so be defensive.

Remember also, there's no harm from sending messages to nil - but there's lots of harm from sending release to objects you don't own, or sending it more than once to objects you do own.

Since your properties are synthesized retain, you can avoid having to send release yourself, and simply use the setter to set them to nil (self.property = nil), assuming of course that you haven't added any extra retains anywhere.

N.B. In your viewDidLoad you've explicitly assigned a newly created object to the iVar that your property has synthesized. Don't do this! If another object has set the property between instantiation and presentation, then it will leak. Only use the _ivar when you know for sure that it is the right thing to do, and you've taken care of every edge case.

TL:DR - Use self.property = nil in both viewDidUnload and dealloc and never assign a new object to an _ivar unless you've checked first that it is already nil or are prepared to release the previous value.