我已经看到了以下片段:
在标题中:
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];
如果我最初的假设是正确的 - 我有兴趣听听是否有'正确'的方法来做这件事,即财产的声明,初始化和内存管理?
答案 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中对象所有权语义的误解。对于在对象上调用的每个init
,copy
或retain
,必须调用release
或autorelease
。这里发生的事情是,对init
的调用与release
或autorelease
没有匹配的调用。
我认为这里令人困惑的是,属性赋值的点符号是方法调用的语法糖。所以看起来它只是一个赋值,实际上它是对属性设置器的调用。
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文件来执行的。