1
votes

I have a general question regarding memory management of properties. Currently, I always use properties without any explicit declaration of related ivars. And, for every retained or copied property I'm releasing its retain count both in dealloc and viewDidUnload methods:

-(void)dealloc{
  [self.myProperty release];
  [self.myOutlet release];
  [super dealloc];
}

- (void)viewDidUnload{
  [super viewDidUnload];
  self.myProperty = nil;
  self.myOutlet = nil;
}

Now, I know that only the outlets and properties retained by the main view should be set to nil in viewDidUnload, and the rest properties should be released in dealloc. But hey, why do I have to bother for every property where it must be released - in dealloc or in viewDidUnload? If some property will be released twice it's OK because it wouldn't crash the app by sending a message to nil object. Putting release in both places (dealloc and unload) saves time and prevents from bugs later when doing code refactoring and forgetting to change release place. Any critics and shouting on that? :)

2

2 Answers

1
votes

If you're using property accessors in -dealloc because you don't have access to the ivar directly, you should do the same in -dealloc that you do in -viewDidUnload:

self.myProperty = nil;

The point of using -release in -dealloc is to avoid calling the accessor, which conceivably could have been overridden by a subclass to have side effects that you don't want in -dealloc, when everything else from the subclass has already been deallocated. But if you're already calling the accessor in -dealloc, you might as well use the setter to release the ivar and ensure that it's done right.

The difference between -dealloc and -viewDidUnload is that you're still working with a complete, fully functional object in -viewDidUnload, whereas the object may already be partially deallocated in -dealloc.

1
votes

My previous answer on this discusses what Apple recommends and why. Relevant portions reproduced here for clarity:

Also, from the Apple docs on -viewDidUnload:

The preferred way to relinquish ownership of any object (including those in outlets) is to use the corresponding accessor method to set the value of the object to nil. However, if you do not have an accessor method for a given object, you may have to release the object explicitly

So, there you go. If your outlet has a property associated with it (which they all should anymore), then nil it in -viewDidUnload -- but don't release it. This makes sense when you consider what is actually happening in a synthesized accessor; the code looks something like this:

- (void) setMyView1 : (UIView *) view {
   if (myView1) // the associated IVAR is already set
      [myView1 release];

   myView1 = [view retain];
}

As you can see, setting a synthesize property to nil implicitly releases the retained object.

Also from the docs in regards to -dealloc:

If you implement this method but are building your application for iOS 2.x, your dealloc method should release each object but should also set the reference to that object to nil before calling super.

Unless you are supporting iOS2.x, there is no need to set objects to nil in dealloc.

So, to summarize Apple's docs regarding -viewDidUnload and -dealloc:

  • In -viewDidUnload, nil properties (including IBOutlet properties), but don't release them
  • In -dealloc release properties, but don't nil them (unless building for 2.x).