对于合成属性,self.target =等效于[self setTarget]吗?

时间:2014-06-09 06:04:28

标签: objective-c

我对这段代码有些怀疑:

@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

3 个答案:

答案 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 asthen 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将自动释放以前的值并保留新值。

可以在dealloc中使用

self.target = nil代替发布,但我强烈建议不要:

  • 它不适用于assign属性(如果他们的ivars因某种原因需要释放)

  • 并非每个需要释放的ivar都会有一个属性,所以你的dealloc最终会混合release和任务分配

  • 自定义设置器可能会产生不必要的副作用

  • 当你的主要(且唯一!)意图是释放一个对象时,你应该发送它release消息,而不是做一些间接调用,这会产生你所需要的副作用。< / p>