18

我已经看过以下代码段很多:

在标题中:

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

在实现文件中:

@synthesize bla;

进而

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

我认为这项任务将 'bla' 的保留计数增加了 2;一次通过 alloc/init 调用,然后通过我们要求通过综合属性设置器发生的保留。

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

在标题中:

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

在实现文件中:

@synthesize bla = _bla;

进而

_bla = [[SomeClass alloc] init];

如果我最初的假设是正确的 - 我很想知道是否有“正确”的方法来做到这一点,即属性的声明、初始化和内存管理?

4

4 回答 4

9

是的,您是对的 - 使用retain属性的综合设置器会增加您已经拥有的实例的引用计数(这alloc意味着所有权)。

只需使用您在初始化程序中提到的第二种形式:

_bla = [[SomeClass alloc] init];

...并记住要修复保留计数,例如:

self.bla = [[[SomeClass alloc] init] autorelease];
于 2010-07-16T06:58:39.050 回答
9

我认为这项任务将 'bla' 的保留计数增加了 2;

真的。

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

您的最后一段代码是正确的方式,但不建议使用前导下划线。属性和 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方法中,但我强烈反对它,因为这会调用不必要的许多方法,并且您无法保证 setter 的行为

于 2010-07-16T06:59:31.773 回答
3

看起来这里的核心问题是对 Cocoa 中对象所有权语义的误解。对于每个init, copyorretain调用对象,必须调用releaseor 。autorelease这里发生的是调用init没有匹配的调用releaseor autorelease

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

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

与以下内容不同:

bla = [[SomeClass alloc] init];

前者翻译为:

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

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

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

于 2010-07-17T06:15:30.037 回答
-3

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

于 2011-05-08T05:40:55.123 回答