财产分配

时间:2012-05-13 06:29:56

标签: iphone objective-c ios ipad

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

@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

:/

2 个答案:

答案 0 :(得分: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保留对象分配给内部变量,从而绕过设置器而不增加retainCount。此外,它还具有内存友好性,因为您只需在实际需要时对象进行实例化。现在,当您将属性设置为nil或某个新对象时,旧对象将被正确释放。

编辑:

在回应Robert Ryan的评论时,我想补充以下内容:

这不会破坏KVO,也不会干扰指定的属性资格。如果您的属性标记为assignweak,那么延迟实例化并不真正有意义。如果它被标记为retainstrong这种实例化对象的方式非常好,特别是当它是你在配置方法中分配的属性时。

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

答案 1 :(得分:0)

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

_cclass = [[CustomeClass alloc] init];

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

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

在你的非ARC项目中,你原来的第二个例子是最好的(使用指针,使用你的属性的setter,然后释放你的指针),因为对于KVO你想养成使用setter的习惯:

CustomeClass *cc = [[CustomeClass alloc] init];
self.cclass = cc;
[cc release];