我们声明了一个属性:
@property (retain) MyClass *myProperty;
Apple示例代码之间有什么区别:
MyClass *aux = [[MyClass alloc] init];
myProperty = aux;
[aux release];
和这一个:
myProperty = [[MyClass alloc] init];
编辑:
发布的原始代码应该是这个:
MyClass *aux = [[MyClass alloc] init];
self.myProperty = aux;
[aux release];
这是我的一个错误,但由于很多答案已经涵盖了我已经保留原始代码的主题。
答案 0 :(得分:3)
这通常是将属性设置为您创建的新值的正确方法。
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
这在init方法中是可以接受的。
myProperty = [[MyClass alloc] init]; // new value retain count 1; there was no old value since the object just init'ed
您发布的代码错误。
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
以下代码巧妙地错了。
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
但是,如果以有趣的方式编写访问器,则可能会遇到麻烦,并且getter不会返回传递给setter的相同对象。例如,它可能会返回某种代理对象。那么你就不会释放你分配的同一个对象。
答案 1 :(得分:1)
self.myProperty = [[MyClass alloc] init]; // this will leak
myProperty = [[MyClass alloc] init]; // this will NOT leak
第一行泄漏是因为它使用属性设置器来分配新对象,并且该属性具有retain的内存模型。因此,除了赋值中的alloc之外,您还可以从属性的setter中获得保留。
但是,第二行不会泄漏,因为它没有使用属性的setter,而是它后面的私有变量。一般来说,你想在除init之外的任何地方使用setter。
因为属性设置器增加了保留计数(对于保留/复制内存模型),所以在属性赋值中看到自动释放的情况并不罕见,如:
self.myProperty = [[[MyClass alloc] init] autorelease]; // Yeah, no leak now
如果你想真正地绕过它,被覆盖的setter可能看起来像这样:
- (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
}
答案 2 :(得分:1)
首先,只是澄清一下声明属性意味着我会稍微解释一下。
声明属性时,实际上是在声明两个方法,即该特定类属性的getter和setter。当您将属性声明为retain
时,您实际上在说通过setter方法设置该属性时,它将被保留。这基本上意味着它的保留计数将增加。
为了使用声明的属性设置class属性,您可以使用点语法,例如self.myProperty
或setter方法,例如-(void)setMyProperty:(MyClass*)newMyClass
,
因此,在您的代码中,即使您声明了某个属性,也没有使用它,因为您没有使用上述任何方法。
现在,
MyClass *aux = [[MyClass alloc] init];
myProperty = aux;
[aux release];
MyClass
对象,现在该对象的保留计数为1. myProperty = [[MyClass alloc] init];
MyClass
对象(保留计数为1)并为其指定了您的类属性myProperty
。所以,总而言之,在第一种情况下,你在内存中创建和对象然后你处理它,而在第二种情况下你创建它但它永远不会被处置。
答案 3 :(得分:0)
在第一种情况下,myProperty具有retainCount 0 在第二种情况下,myProperty具有retainCount 1 如果你在第一种情况下使用 self.myProperty = aux ,那么aux和myProperty的retainCount将为1。