你不能完全停止创建实例变量(instance variables),但如果你有属性,可以停止声明它们。如果你合成了一个属性(synthesize a property),并且没有声明过实例变量,那么它将被为你声明,因此你正在创建实例变量,只是不显式地创建。
曾经的建议是为所有东西创建属性,因为使用合成的属性几乎可以为您完成所有的保留和释放操作。然而,随着ARC的出现,使用属性来封装内存管理的原因已经消失了。现在(对于ARC),建议使用属性来声明您的外部接口,但在变量是对象的内部状态的情况下,使用直接实例变量。
这是采用ARC的好理由:属性回归到它们真正的目的,即成为类的API的一部分,而不再需要将其用作隐藏内存管理工作的hacky方法。
编辑
还有一件事:现在可以在@implementation
中声明实例变量,因此现在无需在@interface
中泄漏任何实现细节。
@implementation MyClass
{
NSString* myString;
}
// method definitions
@end
我非常确定它在分类中也有效。 - 请参见下面的评论
我建议将所有内容声明为属性,避免手动创建实例变量。手动创建实例变量没有任何好处。在你的头文件 @interface
中声明公共属性,在 .m 文件中的私有类扩展中声明私有属性。
对于JeremyP所说的一些观点,尽管内存管理不再是一个重要问题,但访问器的内部使用仍然具有显着的价值。它确保 KVO 正常工作,更好地支持子类,支持自定义设置器(特别是对于像 NSTimer
这样的东西),支持自定义获取器(如惰性实例化)等。混合访问器和实例变量极易出错。很容易忘记需要以哪种方式访问哪个变量。一致性是良好 ObjC 的标志。
如果您绝对必须声明某个实例变量,那么应该像 JeremyP 所说的那样在 @implementation
块中进行声明。
更新(Oct-2013):
Apple 指导方针(来自 Programming with Objective-C: Encapsulating Data):
大多数属性由实例变量支持
通常,即使您从其自身的实现中访问对象的属性,也应该使用访问器方法或点语法进行属性访问,在这种情况下,应该使用
self
:...
这个规则的例外是在编写初始化、释放或自定义访问器方法时,如本节后面所述。
你总是可以从外部访问属性。因此,如果你想让一个变量只能在类内部被读取,你仍然需要声明一个 iVar。此外,使用 object->ivar
访问公共 iVar 比使用方法调用略快。
->
获取内部 ivars 虽然比使用 setter 更快,但几乎从来不是正确的答案。当你进行这种优化时,几乎总会有更好的优化方法可以代替。这是一种非常危险的技术,不适合普遍使用。 - Rob Napier
@synthesize
只是通过添加标准的访问器集合来自动化最常见的实现模式之一。没有什么能阻止你定义自己不同的访问器。 - JeremyP