Tuesday, March 15, 2011

Objective-C 2.0; Assigning a Property; Leaking Memory?

I'm still learning about Objective-C memory management. I'm trying to implement several simple classes in an example program that I'm building.

As an example, say I have the following class definition:

 #import <UIKit/UIKit.h>

 @interface customViewController : UIViewController 
 {
    customObject *myCustomObject;
 }

 @property (retain) customObject *myCustomObject;

 - (void)replaceCustomObject:(customObject *)newObject;

 @end

For the property, I use the standard synthesize keyword...

@synthesize myCustomObject;

Then please assume that in the instance of customViewController the myCustomObject is already set with a valid value and is in use. Then the method replaceCustomObject is defined as:

 - (void)replaceCustomObject:(customObject *)newObject
 {
     //Does this cause a memory leak because I just assign over
     //the existing property? 
     self.myCustomObject = newObject;
 }

As the comment asks, does this leak memory? Or is this the valid way to replace a previous object with a new object?

Thank you,
Frank

From stackoverflow
  • That's perfectly valid, and does not leak memory. The synthesized accessors manage retain counts correctly.

    (As an aside, you don't need that replaceCustomObject: method; since your property is readwrite by default, you have an auto-generated setCustomObject: method that clients of your class can use, and which follows the normal Cocoa naming conventions.)

    Frank V : I know I don't need the replaceCustomObject: method. That was just a way for me to illustrate my overall goal. As you can imagine, where I'm using this is much more than just assigning a property. :-) Thank you for answering my question.
  • the property accessor syntax

    self.x = y;
    

    has the same effect as calling the setter method explicitly:

    [self setX:y];
    

    The accessor method will do whatever it has been written to do. In your case, for a @property(retain) property that has been @synthesized, the accessor will release the old object and retain the new one.

    So, calling the setter, whether explicitly or through the '.' syntax, will do the right thing - including the right memory management.

    So in short: no, this will not leak memory.

  • According to this, if you use (retain) in your declaration, the synthesized method will release the old value first, then retain the new one:

    if (property != newValue) {
        [property release];
        property = [newValue retain];
    }
    
  • As others have mentioned, your code is perfectly valid and won't leak memory when assigning to the property.

    If you have forgotten to implement a proper dealloc method, the last object assigned will be leaked when your customViewController is destroyed. A proper dealloc implementation would look like so:

    - (void)dealloc
    {
        self.myCustomObject = nil;
        [super dealloc];
    }
    
    Frank V : Can you explain further? I've never seen setting a property to nil. Is this equal to doing [self.myCustomObject release] ? This is how I learend to take care of this in the dealloc method...
    rpetrich : Sending [self.myCustomObject release] is dangerous because after doing so, self.myCustomObject still points to the now-released object! In the dealloc method it is probably safe since self is being destroyed anyway, but I dislike having special rules to remember. To be safe, you could also do the following instead: [myCustomObject release]; myCustomObject = nil;

0 comments:

Post a Comment