Garbage collection and retain/release in property setters
When reading about Objective-C properties, I have always been told to make setters (or let the property mechanism make setters) like this:
- (void)setMyProperty:(MyClass *)newValue
{
[newValue开发者_Python百科 retain];
[ivInstanceVariable release];
ivInstanceVariable = newValue;
}
// or
- (void)setMyProperty:(MyClass *)newValue
{
[ivInstanceVariable autorelease];
ivInstanceVariable = [newValue retain];
}
I don't get it. I know that retain
increments the object counter and release
decrements it for the garbage collector, but how can a simpler:
- (void)setMyProperty:(MyClass *)newValue
{
ivInstanceVariable = newValue;
}
lead to memory leaks? Thanks.
When your set method is called, you don't know what the retain count on the object being passed is. It might be 1 and release might be called right after your set method is called.
It's the set method's responsibility to indicate that the object should not be released by calling retain on it.
As for calling release, when a new value is being set, your set method should call release on the old value to indicate that it no longer needs it around.
Finally, you should call retain on the new value and release on the old value, in that order, because it's possible that you'll be passed the exact same value that was already set.
The classic pattern for a "nonatomic retain" setter is...
- (void)setMyProperty:(MyClass *)newValue
{
if (ivInstanceVariable != newValue) {
[ivInstanceVariable release];
ivInstanceVariable = [newValue retain];
}
}
The if test ensures that newValue is different, and that you're not spinning your wheels calling release and retain on the current object. The additional overhead isn't too bad with retain, but using copy it's another matter...
- (void)setMyProperty:(MyClass *)newValue
{
if (ivInstanceVariable != newValue) {
[ivInstanceVariable release];
ivInstanceVariable = [newValue copy];
}
}
精彩评论