Reputation: 1921
We have a property declared:
@property (retain) MyClass *myProperty;
What is the difference between this one from Apple example Code:
MyClass *aux = [[MyClass alloc] init];
myProperty = aux;
[aux release];
and this one:
myProperty = [[MyClass alloc] init];
Edited:
The original code posted should have been this one:
MyClass *aux = [[MyClass alloc] init];
self.myProperty = aux;
[aux release];
It was an error of mine, but since many answers have covered the topic I have leave the original code.
Upvotes: 0
Views: 131
Reputation: 27354
self.myProperty = [[MyClass alloc] init]; // this will leak
myProperty = [[MyClass alloc] init]; // this will NOT leak
The first line leaks because it is using the property setter to assign a new object and the property has a memory model of retain. So, in addition to the alloc in the assignment, you get a retain from the property's setter.
However, the second line will not leak as it is not using the property's setter but the private variable behind it. Generally speaking, you want to use the setter everywhere except in init.
Because property setters increase the retain count (for retain / copy memory models), it's not uncommon to see an autorelease in property assignments like:
self.myProperty = [[[MyClass alloc] init] autorelease]; // Yeah, no leak now
If you want to really wrap your head around it, an overridden setter might look something like this:
- (void) setMyProperty:(MyClass*)newMyProperty
{
MyClass *oldValue = _myProperty;
// replace retain with copy if you want copy to be memory model
_myProperty = [newMyProperty retain];
[oldValue release]; // release last in case newMyProperty == oldValue
[...] // super cool setter behavior here
}
Upvotes: 1
Reputation: 22930
In first case myProperty have retainCount 0.
In second case myProperty have retainCount 1.
If you will use self.myProperty = aux in first case then retainCount of aux and myProperty will be 1.
Upvotes: 0
Reputation: 9162
This is generally the right way to set a property to a new value you've created.
MyClass *aux = [[MyClass alloc] init]; // new value retain count 1
self.myProperty = aux; // new value retain count 2; IMPORTANT: old value retain count decremented
[aux release]; // new value retain count 1, correct since it's retained by self
This is acceptable in the init method.
myProperty = [[MyClass alloc] init]; // new value retain count 1; there was no old value since the object just init'ed
The code you posted is wrong.
MyClass *aux = [[MyClass alloc] init]; // new value retain count 1
myProperty = aux; // new value retain count 1
[aux release]; // new value retain count 0!! deallocated; myProperty points to invalid memory
The following code is subtly wrong.
self.myProperty = [[MyClass alloc] init]; // new value retain count 1 for alloc + 1 for assigned to retain property
[self.myProperty release]; // normally new value retain count 1, correct
However you might get into trouble if the accessors are written in a funny way, and the getter doesn't return the same object you passed into the setter. Perhaps it returns some sort of proxy object, for example. Then you would not be releasing the same object you alloc'ed.
Upvotes: 3
Reputation: 8163
Firs of all, just to clarify a little bit what declaring a property means I will explain it a little.
When you declare a property, you are actually declaring two methods, a getter and a setter for that particular class attribute. When you declare a property as retain
you are actually saying that when you set that property through the setter method, it will be retained. That basically means that its retain count will be incremented.
In order to set the class attribute using the property declared, you can either use dot syntax, e.g. self.myProperty
or the setter method, e.g. -(void)setMyProperty:(MyClass*)newMyClass
,
So, in your code, even though you are declaring a property, you are not making use of it because you are not using any of the methods stated above.
Now,
MyClass *aux = [[MyClass alloc] init];
myProperty = aux;
[aux release];
MyClass
object, now that object has retain count of 1. myProperty = [[MyClass alloc] init];
MyClass
object (it has retain count of 1) and assign it your class attribute myProperty
.So, to sum up, in the first case you create and object in memory and then you dispose it, whereas in the second one you are creating it but it never gets disposed.
Upvotes: 1