开发者

When to "release" after setting a property/instance variable?

开发者 https://www.devze.com 2023-04-08 05:52 出处:网络
We have a property declared: @property (retain) MyClass *myProperty; What is the difference between this one from Apple example Code:

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.


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.


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];
  1. You alloc a MyClass object, now that object has retain count of 1.
  2. You assign it to your class attribute (w/o using the property) so the retain count is still 1.
  3. You release that object so its retain count is 0 and it gets released.

myProperty = [[MyClass alloc] init];

  1. You alloc a 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.


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
}


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消