【发布时间】:2012-05-13 00:44:17
【问题描述】:
在使用 Objective-C 属性时,您是否可以完全停止创建实例变量,或者显式实例变量(不是由属性合成的实例变量)仍然用于属性不合适的用途?
【问题讨论】:
标签: objective-c ios cocoa instance-variables
在使用 Objective-C 属性时,您是否可以完全停止创建实例变量,或者显式实例变量(不是由属性合成的实例变量)仍然用于属性不合适的用途?
【问题讨论】:
标签: objective-c ios cocoa instance-variables
这个问题在here之前已经解决了
当您使用synthesize 时,会为您处理和实例化实例变量。如果您在新版本的 XCode 中使用 Lion,还请查看 ARC 中的各种属性in Transitioning to ARC
【讨论】:
您始终可以从外部访问属性。因此,如果您只想从类内部读取变量,您仍然必须声明 iVar。使用object->ivar 访问公共 ivar 也比使用方法调用稍快。
【讨论】:
-> 直接获取内部 ivars 比 setter 更快,但它几乎永远不是正确的答案。当您进行这种优化时,您几乎总是应该进行更好的优化。这是一种非常危险的技术,不适合一般使用。
你能完全停止创建实例变量吗
不,你不能(在某种意义上)。如果您有属性,您可以做的是停止声明它们。如果您合成了一个属性并且您没有声明 instvar,它将为您声明,因此您正在创建一个实例变量,而不是显式地。
它们是否仍然用于属性不合适的目的?
它曾经是为所有内容创建属性的建议,因为合成属性会为您完成几乎所有的保留和释放。然而,对于 ARC,使用属性来包装内存管理的理由已经消失。现在(对于 ARC)的建议是,我相信,使用属性来声明您的外部接口,但使用直接实例变量,其中变量是对象内部状态的一部分。
这是采用 ARC 的一个很好的理由:属性恢复到它们的真正目的,只是作为类 API 的一部分,并且不再需要将它们用作隐藏内存管理工作的骇人听闻的方式。
编辑
还有一件事:您现在可以在@implementation 中声明实例变量,因此现在无需在@interface 中泄露任何实现细节。即
@implementation MyClass
{
NSString* myString;
}
// method definitions
@end
而且我很确定它也适用于类别。 - 请参阅下面的评论
【讨论】:
@synthesize 它们。
@synthesize 只是通过添加一组标准访问器来自动化最常见的实现模式之一。没有什么可以阻止您定义自己的不同访问器。
我建议将所有内容都声明为属性并完全避免手动 ivars。手动创建 ivars 并没有真正的好处。在标题 @interface 中声明公共属性,在 .m 文件的私有类扩展中声明私有属性。
对于 JeremyP 的某些观点,在 ARC 下,访问器的内部使用仍然具有重要价值,尽管内存管理不再是一个重要问题。它确保 KVO 正常工作,更好地子类化,支持自定义 setter(特别是像 NSTimer 这样的东西),支持自定义 getter(例如延迟实例化)等。混合使用访问器和 ivars 非常容易出错.忘记您需要以哪种方式访问哪个太容易了。一致性是好的 ObjC 的标志。
如果您出于某种原因绝对必须声明一个 ivar,那么您应该按照 JeremyP 的说明在 @implementation 块中进行声明。
更新(2013 年 10 月):
Apple's guidance(来自 Objective-C 编程:封装数据):
大多数属性都由实例变量支持
一般来说,您应该使用访问器方法或点语法进行属性访问,即使您是从其自己的实现中访问对象的属性,在这种情况下您应该使用
self:...
此规则的例外是在编写初始化、解除分配或自定义访问器方法时,如本节后面所述。
【讨论】: