带有合成属性的alloc + init - 它会导致保留计数增加2吗?

时间:2010-07-16 06:56:11

标签: iphone objective-c memory-management properties retain

我已经看到了以下片段:

在标题中:

SomeClass *bla;
@property(nonatomic,retain) SomeClass *bla;

在实施文件中:

@synthesize bla;

然后

self.bla = [[SomeClass alloc] init];

我认为这项任务将'bla'的保留计数提高了两倍;一旦通过alloc / init调用,然后通过我们要求通过合成属性设置器发生的保留。

因此,我通常会声明我的属性:

在标题中:

SomeClass *_bla; // note the underscore
@property(nonatomic,retain) SomeClass *bla;

在实施文件中:

@synthesize bla = _bla;

然后

_bla = [[SomeClass alloc] init];

如果我最初的假设是正确的 - 我有兴趣听听是否有'正确'的方法来做这件事,即财产的声明,初始化和内存管理?

4 个答案:

答案 0 :(得分:8)

是的,你是对的 - 使用retain属性的合成setter会增加你已经拥有的实例的引用次数(因为alloc意味着所有权)。

请使用初始化程序中提到的第二种形式:

_bla = [[SomeClass alloc] init];

...并且记得另外修复保留计数,例如:

self.bla = [[[SomeClass alloc] init] autorelease];

答案 1 :(得分:8)

  

我认为这项任务将'bla'的保留计数提高了两倍;

真。

  

我很想知道是否有'正确'的方法来做到这一点

您的最后一段代码是正确的方法,但不建议使用前导下划线。该物业和ivar可以共享相同的名称。刚

@interface Foo : Bar {
  SomeClass* bla;
}
@property (nonatomic, retain) SomeClass* bla;
@end

@implementation Foo
@synthesize bla;
-(id)init {
   ...
   bla = [[SomeClass alloc] init];
   ...
}
-(void)dealloc {
  [bla release];
  ...
  [super dealloc];
}

就够了。


有些人可能会使用

SomeClass* foo = [[SomeClass alloc] init];
self.bla = foo;
[foo release];

self.bla = [[[SomeClass alloc] init] autorelease];
-init方法中的

,但强烈反对,因为这会不必要地调用许多方法,and you cannot guarantee the behavior of the setter

答案 2 :(得分:3)

看起来这里的核心问题是对Cocoa中对象所有权语义的误解。对于在对象上调用的每个initcopyretain,必须调用releaseautorelease。这里发生的事情是,对init的调用与releaseautorelease没有匹配的调用。

我认为这里令人困惑的是,属性赋值的点符号是方法调用的语法糖。所以看起来它只是一个赋值,实际上它是对属性设置器的调用。

self.bla = [[SomeClass alloc] init];

与以下内容不同:

bla = [[SomeClass alloc] init];

前者转化为:

[self setBla: [[SomeClass] alloc] init]];

而后者实际上是一项任务。

要解决您的问题,您真正需要做的就是确保调用init的代码调用autorelease,以便在设置者retain调用后保留计数将减少

答案 3 :(得分:-3)

没有重复计算。由synthesize创建的setter在执行保留之前执行释放。请参阅苹果网站上引用的目标c类3的斯坦福大学课程。值得注意的是,在iboutlet的情况下,不需要alloc init,因为它是通过加载xib文件来执行的。