有人可以帮我理解Objective C属性中的引用计数。
假设我有课
@interface TA : NSObject
{
TB* tb;
}
- (id) init;
- (void) dealloc;
@property (nonatomic,retain) TB* tb;
@end
@implementation
@synthesize tb;
- (id) init {...}
- (void) dealloc {...}
@end
我的理解是将新值赋给“tb”,例如“ta.tb = newValue”等同于以下逻辑:
if (newValue != oldValue)
{
[newValue retain];
[oldValue release];
tb_storage_cell = newValue;
}
但是它如何在 init 方法中起作用?
[TA alloc] 是否用零预初始化实例内存?
我是否需要在 init 中执行 tb = nil ?
如果alloc使用零预先初始化内存,则在 init 中设置 tb = nil 是不必要的,因为tb已经是nil。是吗?
另一方面,如果 alloc 没有将已分配的内存清零,并且它包含垃圾,那么setter在初始化赋值中释放旧值的尝试应该会崩溃并且它可能永远不会工作。那么这是否意味着确实会确保alloc返回始终为零的内存块?
接下来, dealloc 。
假定的序列在 dealloc 里面是:
[tb release];
tb = nil;
[super dealloc];
是吗?
但如果是这样,它又如何运作?首先发布应该发布“tb”。然后赋值“tb = nil”应该再次释放tb的oldValue,所以它应该等于双重释放并崩溃......
或者我应该跳过 dealloc 中的“[tb release]”而只是做
tb = nil;
[super dealloc];
答案 0 :(得分:3)
Objective-C规范明确指出所有对象实例在分配时都将其成员清零。
只有在使用instance.property语法时才会调用属性的get和set方法。你的“tb = nil”行只是将实例变量的值设置为nil,而不是调用属性。
您必须执行self.tb = nil才能调用属性setter。在dealloc方法中释放值时,通常应始终使用属性语法。
self.tb = nil;
这将正确释放并取消财产。
答案 1 :(得分:0)
您可以将您的方法编写为:
-(id) init{
if(self=[super init]){
tb = [[TB alloc] initWithSomething];
}
return self;
}
- (void) dealloc{
[tb release];
[super dealloc];
}
- (void) someMethod{
NSLog(@"This is ok since tb is always initialized. %@", [tb description]);
NSLog(@"This is also ok. %@", [tb description]);
}
这是一个典型的初始化,或者如果你认为tb不必从开始初始化,那么你可以让它变得懒惰:
-(tb) tb{
if (!tb)
tb = [[TB alloc] initWithSomething];
return tb
}
-(id) init{
self=[super init];
return self;
}
- (void) dealloc{
[tb release];
[super dealloc];
}
- (void) someMethod{
NSLog(@"This might be not ok, tb is not necessarily initialized:%@ ", [tb description]);
NSLog(@"This is ok since tb is always initialized by the getter. %@", [self.tb description]);
}
通过执行此操作,您必须使用属性调用tb以确保已初始化,除非您在代码的其他部分初始化它。