views:

499

answers:

5

Something I have been wondering about properties for a while. When you are using properties, do you need to override the release message to ensure the properties are released properties?

i.e. is the following (fictitious) example sufficient?

@interface MyList : NSObject {
NSString* operation;
NSString* link;
}
@property (retain) NSString* operation;
@property (retain) NSString* link;
@end

@implementation MyList
@synthesize operation,link;
@end
+1  A: 

No, you override the -dealloc method. And yes, if you don't release your properties (or rather, the backing ivars), you will leak. So in your @implementation here you should have something like

- (void)dealloc {
    [operation release];
    [link release];
    [super dealloc];
}
Kevin Ballard
+9  A: 

You should always release the backing variables in dealloc:

- (void) dealloc {
   [operation release];
   [link release];

   [super dealloc];
}

Another way:

- (void) dealloc {
   self.operation = nil;
   self.link = nil;

   [super dealloc];
}

That's not the preferred way of releasing the objects, but in case you're using synthesized backing variables, it's the only way to do it.

NOTE: to make it clear why this works, let's look at the synthesized implementation of the setter for link property, and what happens when it is set to nil:

- (void) setLink:(MyClass *) value {
   [value retain]; // calls [nil retain], which does nothing
   [link release]; // releases the backing variable (ivar)
   link = value;   // sets the backing variable (ivar) to nil
}

So the net effect is that it will release the ivar.

Philippe Leybaert
Actually, if you're using synthesized ivars (ie, you declare the property but not a corresponding ivar), then an ivar will be generated for you. See my question here: http://stackoverflow.com/questions/1283419
Dave DeLong
Some compilers didn't synthesize the ivar. That was fixed after the first compiler that supported synthesized ivars was released. Hence the confusion.
bbum
@bbum good to know! thanks for the clarification.
Dave DeLong
Better still, move from managed memory to garbage collection. Then, the example would be fine as written.
Jeremy W. Sherman
Lol, someones a java developer (:
Jacob
@Jacob — You are aware that Objective-C 2.0 introduced garbage collection, correct? It may not apply in every situation (such as iPhone or when using frameworks that don't support it) but it's a great solution when you can use it, especially with the improvements in Snow Leopard. The garbage collector tends to be extremely smart and speedy. :-)
Quinn Taylor
+3  A: 

In non-GC applications, yes. It is usual to assign nil instead of releasing the ivars. My best experience is to release ivars initialized with init and assign nil to properties with retain and copy mode.

In your case I would assign nil

- (void) dealloc {
   self.operation = nil;
   self.link = nil;
   [super dealloc];
}
cocoafan
This is the _only_ correct way to do it.
Georg
@gs not correct. You can release the ivar and set them to nil directly. Using the accessors can have odd side effects in rare circumstances. If you're observing a property on an object, and the object is set to nil, your observer might try to get other info from the obj, but if the set-to-nil happened in a -dealloc, strange things could happen.
Dave DeLong
This is a quirk of the syntax. One wishes that a synthesized or implicit"@properties_release();" could just be added to the dealloc method, in some future language spec. If objective-C 2.0 was going to be all things to all people, it seems bizarre to recommend something like this accessor-syntax, and then have to place a caveat on it about observers and property accessors in destructors.
Warren P
+1  A: 

Synthesizing a property only creates getter and setter methods, and therefor won't release the ivar when the object is deallocated. You need to release the ivar yourself.

Tom Dalling
That only applies to declared properties that do *not* use the default (assign) attribute. Search for Apple's "Objective-c 2.0 Programing Guide" and read the section on "Declared Properties", particularly the part about dealloc. I Quote: "Declared properties do, however, provide a useful way to cross-check the implementation of your dealloc method: you can look for all the property declarations in your header file and make sure that object properties not marked assign are released, and those marked assign are not released."
Elise van Looij
+2  A: 

The best way to do this is:

- (void)dealloc {
    [operation release], operation = nil;
    [link release], link = nil;

    [super dealloc];
}

It would indeed be more convenient to use the generated setter methods

self.operation = nil;

but that is frowned upon. You don't always know which thread an object is deallocated on. Thus using an accessor may cause problems by triggering KVO notifications.

The catch here is that you need to adapt your dealloc to match the object management policy defined in your @property. E.g. don't go releasing a iVar backing an (assign) property.

Pierre Bernard