实际的区别如下。
通过使用属性访问器将属性设置为nil,将使合成方法在释放现有属性后掌握您的新nil属性。
// we will take for granted that you synthesize this property
@property (nonatomic, retain) IBOutlet UILabel* label;
我们将使用属性访问器并将其设置为nil。
//This will in actuality set the new value of nil to the label variable after
//releasing the existing label that it had a retain count on.
self.label = nil;
接下来我们将直接发布它。
//This line on the other hand will merely release the label directly.
//As soon as the label is deallocated you will have a handle to an invalid object.
//(memory space that used to be your label)
[label release];
现在我们将展示属性访问器的简化版本。(仅供参考,不可直接使用)
//Simply put the following is an pseudo equivalent of the property setter.
[label release]
label = nil
重点在于属性访问器会处理释放它所保留的标签,然后将其设置为你传递的值(在本例中为nil)。
因此,添加以下代码:
label = nil
如果不释放保留的对象,会导致内存泄漏,并且您将对一个标签保留计数,而您不再拥有指针。
注意:
还有一件事情需要考虑。任何空指针都可以接受消息。而它们将以nil作为回复。另一方面,已释放的对象,一旦该内存被释放,您对其发送的消息很可能会引发错误。结果是不可预测的。这是将属性设置为nil的好理由。它不仅会处理它所持有的对象的释放,而且还会给您一个可以安全地发送消息而不会崩溃的对象。
@WaltSellers的一个好观点
在完全释放变量之后访问变量(无论是属性访问器还是实例变量)将导致“未定义”的操作。这意味着访问可能正常运行,或者可能破坏应用程序的其他部分,或者可能会迅速崩溃并终止有问题的应用程序。基本上,在释放后将变量设置为nil将使您能够通过该错误。
我提供的另一个提示
为了克服属性访问器和实例变量的误解,我只是@synthesize并告诉它设置一个变量名。
@synthesize label = _label
这样做可以区分self.label和它的实例变量。现在,您不能直接访问label变量,而是需要加上前缀_。
-setPropertyName:
的方法来实现它们。在此setter中,您可以做任何想做的事情,包括执行不适合在dealloc
内部执行的操作,例如保留self。同样,在dealloc
内部使用KVO通知是一个坏主意。这一点应该很明显。您的对象正在消失 - 没有人应该得到您拆除ivars的详细信息。 - Lily Ballardself
是一个@property
的评论。这个概念没有任何意义。属性属于对象。如果self
是一个属性,那它会属于哪个对象呢?实际上,self
只是Obj-C编译器插入的方法调用的隐式参数。您可以使用self->ivarName
引用实例变量,这在功能上与仅使用ivarName
相同。 - Lily Ballardself.label
。在这些情况下,使用label
。self->label
结构只有在-copyWithZone:内部或某些情况下(通常在此处将使用属性)才真正有用,并且在其他地方被认为是不好的形式。 - Lily Ballard