我对这段代码有些怀疑:
@interface Foo {
id target_;
}
@property (nonatomic, readwrite, retain) id target;
@implementation Foo
@synthesize target = target_;
-(id)initWithTarget:(id)t {
if( (self=[super init]) ) {
self.target = t;
}
return self;
}
-(void) dealloc {
[target release];
[super dealloc];
}
@end
问题:
self.target = t
是否完全等同于[self setTarget:t]
?
target = t
呢?target
,对吧?self.target = nil
方法中调用dealloc
是完全可以的,对吗?因为setter会释放target
。答案 0 :(得分:2)
是。该文档对合成属性的工作方式有entire section。
target = t
无法正常工作,因为既没有实例变量也没有名为target
的局部变量。
要设置属性,必须使用self.target = t
或[self setTarget:t]
。
您仍然可以使用target_
直接访问ivar,因为它是如何在您的标头中声明的,但自然这样做不会触发访问者。
只有在确定使用属性设置器进行分配时才会保留,并且该属性被声明为retain / strong(默认情况下是这样)。
如果您不使用ARC来管理您的引用(您确实应该这样做),则应在-dealloc
中手动释放ivars,而不是将其属性设置为nil:
-(void) dealloc {
[target_ release];
[super dealloc];
}
答案 1 :(得分:1)
self.target = t是否完全等同于[self setTarget:t]?
是。 self.target =
几乎相当于setTarget:
。在某些情况下,它们都会编译为完全相同的二进制文件,在其他情况下self.target =
会有微妙的差异,使其执行速度比setTarget:
快,但行为方式相同。
如果是,那么target = t?
不,这不一样。你应该避免做target_ =
- 这种方法是直接访问C指针,这可能会导致各种问题。有一些边缘情况你需要这样做,但一般情况下应该尽可能避免。
如果是,则保留目标,对吧?
如果您已禁用ARC ,并将其声明为retain
,则self.target =
和setTarget:
将保留,但target_ =
将不会保留,并且可能会导致以后崩溃。如果该属性未声明为retain
,则永远不会保留。
如果您启用了ARC且s declared as
强then all three styles of setter will retain the variable. If it's declared as something else (such as
弱'),则不会在所有三种情况下保留。
在dealloc方法中调用self.target = nil会很好,对吧?因为setter会释放目标。
一般建议不要在dealloc中使用self.target =
或setTarget:
。使用[target_ release]; target_ = nil
。或者甚至更好,启用ARC并且不要在dealloc中使用target做任何事情。
答案 2 :(得分:1)
是的,self.target = t
完全等同于[self setTarget:t]
。
target = t
语法不起作用;点语法是必需的。 target_ = t
会,但不会是同一件事:没有调用任何方法,KVO观察员不会被通知,并且不会保留该值。
retain
属性的合成setter将自动释放以前的值并保留新值。
self.target = nil
代替发布,但我强烈建议不要:
它不适用于assign
属性(如果他们的ivars因某种原因需要释放)
并非每个需要释放的ivar都会有一个属性,所以你的dealloc最终会混合release
和任务分配
自定义设置器可能会产生不必要的副作用
当你的主要(且唯一!)意图是释放一个对象时,你应该发送它release
消息,而不是做一些间接调用,这会产生你所需要的副作用。< / p>