繁体   English   中英

每个伊娃都必须是财产吗?

[英]Must every ivar be a property?

我看到它在为iOS编码时建议应该使用属性来访问实例变量,因为这会给内存管理带来诸多好处。

这个建议并不适合我。 我发现使用属性而不是普通的旧ivars只需要太多的代码,如果你对内存管理感到满意,我并没有真正看到它的好处。 它真的那么重要吗? 您管理实例变量的方法是什么?

没有必要为所有ivars声明属性。 想到几点:

  • 如果ivar仅在对象的生命周期中被分配一次,那么通过声明属性你并没有真正获得任何东西。 只需在init期间保留/复制/分配,然后在dealloc期间根据需要释放。
  • 如果要经常更改ivar,声明属性并始终使用访问器将更容易避免内存管理错误。
  • 如果属性和ivars是私有的,则可以在.m文件而不是.h文件中的类扩展中声明属性。
  • 在定位iOS 4.0+时,如果定义属性并合成访问者,则无需在标题中声明ivars。

所以我通常使用属性,但对于一个对象在init期间分配的NSMutableArray并用于保存一堆whatevers的东西,我将使用一个普通的旧ivar,因为我永远不会重新分配ivar。

虽然丹尼尔的答案是正确的,但我认为它错过了一个重要的观点。 即:

我发现使用属性而不是普通的旧ivars只需要太多的代码,如果你对内存管理感到满意,我并没有真正看到它的好处。

好处是一致性; 一致的内存管理和一致的行为。

值得注意的是,这两行代码在运行时实际上可能具有极其不同的行为:

iVar = [foo retain];
self.iVar = foo;

第一个是实例变量的直接设置,不会有更改通知。 第二个遍历setter,因此,在设置时保留任何子类自定义, 确保向属性的任何观察者通知更改

如果您在整个代码中直接使用ivars(在类的内部 - 如果您直接从该实例外部使用实例的ivars,那么......任何处理您的代码库的承包商应该加倍他们的费率;),那么您必须或者也可以手动处理更改通知传播(通常通过调用willChangeValueForKey: / didChangeValueForKey明确设计应用程序以避免使用依赖于键值观察的机制。

你说“需要太多代码”。 我没有看到; 在上面两行代码中,点语法是较少的字符。 即使使用传统语法调用setter方法也会减少代码。

并且不要忽视集中内存管理的价值; 在无数的呼叫站点和崩溃的城市中发生了一次意外遗漏。

属性只是语法糖,可以避免一遍又一遍地编写相同的方法。 使用属性,您可以使用一个setter来释放旧对象并免费保留新对象。

对于私有字段 - 我建议仅对原始类型(BOOL / int / float等)使用直接ivars是安全的。 我找到了一个很好的做法,包括与属性中的内存管理相关的所有内容 - 甚至很少使用的字段。 这种方法的另一个好处是IDE通常以不同的方式突出显示直接的ivars访问,因此您总是可以很好地分离简单的标量字段和对象类型字段。

与此相反,我强烈反对课堂公共界面中的任何直接ivars 由于语言的动态特性,它可能导致极难找到,本地化和修复的运行时错误。 考虑以下层次结构

@interface BaseControl
...
@end

@interface Label : BaseControl
...
@end

@interface Button : BaseControl {
  @public
    BOOL enabled;
}
@end

和一个代码片段

- (void)enableAllButtons {
    NSArray *buttons = [self getAllButtons];   // expected to contain only Button instances
    for (Button *button in buttons) {
        button->enabled = YES;
    }
} 

现在想象-getAllButtons逻辑中的某个地方有一个错误,你也会在该数组中返回一些Label - 所以那些Label类实例将被分配的ivar缺失。 可能令人惊讶的事实是-enableAllButtons在这种情况下不会崩溃。 但在那时,那些Label实例的内部结构已经损坏 ,这导致未定义的行为,并在其他地方使用时崩溃。

就像内存管理中的一些流行问题(通常是悬挂指针) - 这种问题很难找到和本地化 - 因为错误的出现通常是远离(在时间,代码或应用流程方面)放置,导致错误。 但是对于这个特殊问题,你甚至没有方便的工具(如泄漏/僵尸分析器等)来帮助你进行本地化和修复 - 即使你学会了如何重现它并且可以轻松地调查错误的状态。

显然,如果你使用@property (assign) BOOL enabled; 您将在-enableAllButtons中获得易于诊断和修复运行时异常的信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM