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

在@ mmalc对这个问题 的 回应中 ,他说:“一般来说,你不应该在dealloc(或init)中使用accessor方法。 为什么mmalc这样说?

我能想到的唯一真正的原因是性能,并避免@dynamic setter的未知副作用。

讨论?

这都是关于使用惯用的一致的代码。 如果对所有代码进行适当的设置,有一组规则可以保证在init / dealloc中使用访问器是安全的。

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

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

这种types的属性初始化允许推迟很多实际上不需要的初始化代码。 在上述情况下,init不负责启动属性状态,并且在init方法中使用访问器是完全安全的(甚至是必须的)。

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

这基本上是一个指导,以尽量减less错误的潜力。

在这种情况下,你的二传手可能会无意中直接或间接地假设对象的状态。 这些假设可能是一个问题,当对象正在build立或被破坏的时候。

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

(你可以争辩说,你的对象应该删除所有的观察者,然后再把自己撕下来,这是很好的做法,另一个防止无意的问题的指导方针)。

 @implementation Example -(void) setFoo:(Foo*)foo { _foo = foo; [_observer onPropertyChange:self object:foo]; } -(void) dealloc { ... self.foo = nil; } @end 

你回答了你自己的问题:

  1. 性能本身可能是一个完全充分的理由(特别是如果您的访问器是primefaces)。
  2. 您应该避免访问者可能产生的任何副作用。

如果你的课程可能被分类,后者尤其是个问题。

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

这可能是setter具有应该运行的逻辑,或者实现使用了一个与getter / setter不同的名称,或者两个需要释放和/或值设置为零的ivars。 唯一确定的方法是打电话给二传手。 在init或dealloc中被调用时,调用者的责任是以不会产生不良副作用的方式来编写。

从“cocoadevise模式”,Buck,Yacktman,第115页:“…当您使用现代Objective-C运行时使用合成实例variables或使用访问器时,

事实上,对于经常进来的类(比如详细视图控制器),你想在init中使用访问器; 否则,你可能会最终发布viewDidUnload中的值,您稍后尝试访问它们(它们显示在CS193P中)

您可以通过在分配/取消分配时不调用setter来创build相同的问题。

我不认为你可以通过在init / dealloc中直接使用retain / release来达到目的。 你只是改变一组可能的错误。

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