3 回答
TA贡献1799条经验 获得超9个赞
虽然丹尼尔的答案是正确的,但我认为它没有抓住重点。即:
我发现使用属性代替普通的旧ivars会花费太多代码,并且如果您对内存管理感到满意,我不会真正看到好处。
好处是一致性;一致的内存管理和一致的行为。
值得注意的是,这两行代码实际上在运行时可能具有截然不同的行为:
iVar = [foo retain];
self.iVar = foo;
第一个是实例变量的直接设置,并且不会有更改通知。第二个过程通过setter进行,因此在设置时保留所有子类自定义项,并确保将更改通知给属性的所有观察者。
如果您在整个代码中直接使用ivars(在类内部-如果您直接从实例外部使用实例的ivars,那么……在您的代码库上工作的任何承包商都应将其费率提高一倍;),那么您必须也可以手动处理更改通知传播(通常通过调用willChangeValueForKey:/ didChangeValueForKey),也可以显式设计应用程序以避免使用依赖于键值观察的机制。
您说“花费太多代码”。我没看到 在以上两行代码中,点语法的字符较少。即使使用传统语法调用setter方法,代码也更少。
并且不要在集中式内存管理中贬低价值;在大量的呼叫站点和崩溃的城市中,一个偶然的遗漏。
TA贡献1836条经验 获得超13个赞
对于私有字段-我建议仅对原始类型(BOOL / int / float等)使用直接ivars是安全的。我发现将与内存管理相关的所有内容包装到属性中的一种很好的做法-甚至是很少使用的字段。这种方法的额外好处是,IDE通常以不同的方式突出显示直接ivar访问,因此您始终可以将简单的标量字段和对象类型字段很好地分开。
与此相反,我强烈建议不要在类公共接口中使用任何直接方法。由于语言的动态性质,它可能导致运行时错误,这些错误非常难以查找,本地化和修复。考虑以下层次
@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,将获得易于诊断和修复的运行时异常。
- 3 回答
- 0 关注
- 478 浏览
添加回答
举报