为什么我不应该在init / dealloc中使用Objective C 2.0访问器?

时间:2008-10-10 19:21:33

标签: objective-c cocoa

@mmalc's responsethis question中,他声称“一般情况下,你应该在dealloc(或init)中使用访问器方法。”为什么mmalc会说这个?

我能想到的唯一真正原因是性能和避免@dynamic制定者的未知副作用。

讨论

6 个答案:

答案 0 :(得分:29)

它基本上是一个最小化错误可能性的指南。

在这种情况下,存在(可能性)你的setter / getter可能无意中对对象的状态做出直接或间接的假设。当对象处于设置或销毁状态时,这些假设可能是一个问题。

例如,在下面的代码中,观察者不知道'Example'正在被销毁,并且可以假设已经释放的其他属性是有效的。

(你可以说你的对象应该在撕下自己之前删除所有观察者,这是一种很好的做法,以及另一个防止意外问题的准则)。

@implementation Example

-(void) setFoo:(Foo*)foo
{
   _foo = foo;
  [_observer onPropertyChange:self object:foo];
}

-(void) dealloc
{
   ...
   self.foo = nil;
}

@end

答案 1 :(得分:19)

所有关于使用惯用的一致代码。如果适当地对所有代码进行模式化,那么有一些规则可以保证在init / dealloc中使用访问器是安全的。

最大的问题是(正如mmalc所说)设置属性默认状态的代码不应该通过访问器,因为它会导致各种令人讨厌的问题。问题是init没有理由设置属性的默认状态。出于多种原因,我一直在转向自我初始化的访问器,如下面的简单示例:

- (NSMutableDictionary *) myMutableDict {
    if (!myMutableDict) {
        myMutableDict = [[NSMutableDictionary alloc] init];
    }

    return myMutableDict;
}

这种属性初始化允许人们推迟许多实际上不必要的初始化代码。在上面的例子中,init不负责启动属性状态,并且在init方法中使用访问器是完全安全的(甚至是必要的)。

不可否认,这会对您的代码施加额外的限制,例如,具有超类中属性的自定义访问器的子类必须调用超类访问器,但这些限制与Cocoa中常见的各种其他限制并不相符。

答案 2 :(得分:15)

你回答了自己的问题:

  1. 性能本身可能是一个非常充分的理由(特别是如果你的访问者是原子的)。
  2. 您应该避免访问者可能产生的任何副作用。
  3. 如果您的班级可能是子类,则后者尤其成问题。

    目前尚不清楚为什么在 Objective-C 2 访问器中专门解决这个问题?无论您是自己使用声明的属性还是写入访问器,都适用相同的原则。

答案 3 :(得分:2)

可能是setter具有应该运行的逻辑,或者实现可能使用名称与getter / setter不同的ivar,或者可能需要释放的两个ivar和/或将其值设置为nil。唯一可靠的方法是打电话给二传手。设置者的责任是以在init或dealloc期间调用时不会发生不良副作用的方式编写。

来自“Cocoa Design Patterns”,Buck,Yacktman,第115页:“......当您使用现代Objective-C运行时的合成实例变量或......时,没有使用访问器的实际替代方法。”

答案 4 :(得分:0)

实际上,对于经常出入的类(如详细视图控制器),您希望在init中使用访问器;否则,您最终可能会在稍后尝试访问的viewDidUnload中释放一个值(它们在CS193P中显示...)

答案 5 :(得分:0)

您可以通过在分配/解除分配时不调用setter来创建相同的问题。

我认为你不能通过在init / dealloc中直接使用retain / release来实现任何目的。您只需更改可能的错误集。

每次你必须考虑财产分配/解除分配的顺序。