1

如果我有一个这样的属性,那么分配第一种模式和第二种模式的属性的值有什么区别?

@interface Prueba : NSObject{
    CustomeClass *_cclass;
}
@property(nonatomic, retain)CustomeClass *cclass;

@end

@implementation Prueba

@synthesize cclass = _cclass

- (void)config{
    // 1 This
    self.cclass = [[CustomeClass alloc] init];

    // 2 This or
    CustomeClass *cc = [[CustomeClass alloc] init];
    self.cclass = cc;
    [cc release];
}

@end

:/

4

2 回答 2

0

您的第一个示例为您提供了一个保留计数为 2(错误)的对象,而您的第二个示例为您提供了一个保留计数为 1(正确)的对象。第二种方法在非 ARC 项目中是首选。或者,您也可以自己设置 ivar(我不喜欢,因为您没有使用 setter):

_cclass = [[CustomeClass alloc] init];

或者像你的例子一样使用setter,但是做一个自动释放(我不喜欢,因为你不应该推迟你的发布,除非你必须这样做):

self.cclass = [[[CustomeClass alloc] init] autorelease];

在您的非 ARC 项目中,您最初的第二个示例是最好的(使用指针,使用属性的设置器,然后释放指针),因为对于 KVO,您希望养成使用设置器的习惯:

CustomeClass *cc = [[CustomeClass alloc] init];
self.cclass = cc;
[cc release];
于 2012-05-13T06:47:31.040 回答
0

结果没有区别,只是在第二种方法中您创建了一个附加指针。在这两个版本self.cclass中都可以很好地保存您的对象。

问题是,当您仅在第二种模式下释放对象时,在第一种模式下您将出现内存泄漏。由于retainCount分配对象时它是 +1,因此您通过 setter 分配一个 +1 对象。这意味着,你实际上又撞上了retainCount。现在,如果您在将对象分配给您的属性后不释放它,一旦它从那里释放,它retainCount只会减少 1。因此让一个带有retainCount+1 的对象在内存中浮动,永远丢失。

但是因为您已经在询问更好的版本,所以我想向您介绍惰性实例化。您可以做的是覆盖相关属性的 getter 方法并检查它是否已被分配。如果没有,则在 getter 方法中分配它,然后返回它。它看起来像这样:

- (CustomeClass*) cclass
{
  if(!_cclass)
  {
    _cclass = [[CustomeClass alloc] init];
  }
  return _cclass;
}

使用此方法,您可以将 +1 保留对象分配给内部变量,从而绕过 setter 而不会增加retainCount. 它也是内存友好的,因为你的对象只有在你真正需要它的时候才会被实例化。现在,当您将属性设置为 nil 或某个新对象时,旧对象将被正确释放。

编辑:

针对 Robert Ryan 的评论,我想添加以下内容:

这不会破坏 KVO,或干扰为您的属性分配的资格。如果你的属性被标记为assignor weak,那么惰性实例化就没有意义了。如果它被标记为retain或者strong这种实例化对象的方式非常好,特别是当它是一个你可以在配置方法中分配的属性时。

关于 KVO:在 getter 内部分配的值可以看作是初始值/默认值,因此 KVO 仍然有效。当您使用 setter 为属性分配其他内容时,它将触发。您不希望 KVO 因为默认值而触发,对吗?

于 2012-05-13T06:35:46.807 回答