Objective c 何时使用实例变量以及何时使用属性

Objective c 何时使用实例变量以及何时使用属性,objective-c,ios,cocoa,instance-variables,Objective C,Ios,Cocoa,Instance Variables,当使用Objective-C属性时,您是否可以完全停止创建实例变量,或者显式实例变量(不是由属性合成的变量)是否仍然用于属性不合适的用途?这个问题以前已经解决过 使用synthesis时,会为您处理和实例化实例变量。如果您在新版本的XCode中使用Lion,还可以查看ARC中的各种属性,您始终可以从外部访问属性。因此,如果您只希望从类内部读取变量,那么仍然必须声明iVar。另外,使用object->ivar访问公共ivar比使用方法调用稍微快一点 您可以完全停止创建实例变量吗 不,你不能(在某种

当使用Objective-C属性时,您是否可以完全停止创建实例变量,或者显式实例变量(不是由属性合成的变量)是否仍然用于属性不合适的用途?

这个问题以前已经解决过


使用
synthesis
时,会为您处理和实例化实例变量。如果您在新版本的XCode中使用Lion,还可以查看ARC中的各种属性

,您始终可以从外部访问属性。因此,如果您只希望从类内部读取变量,那么仍然必须声明iVar。另外,使用
object->ivar
访问公共ivar比使用方法调用稍微快一点

您可以完全停止创建实例变量吗

不,你不能(在某种意义上)。如果您有属性,您可以停止声明它们。如果您合成了一个属性,但尚未声明instvar,那么它将为您声明,因此您正在创建一个实例变量,而不是显式的

它们是否仍然用于不适当的财产用途

它曾经是为所有内容创建属性的建议,因为合成属性可以为您完成几乎所有的保留和发布。然而,随着ARC的出现,使用属性包装内存管理的理由已经消失了。现在(对于ARC)的建议是,我相信,使用属性来声明外部接口,但使用直接实例变量,其中变量是对象内部状态的一部分

这是采用ARC的一个很好的理由:属性恢复到它们的真正目的,只是作为类API的一部分,并且不再需要使用它们作为隐藏内存管理工作的黑客方式

编辑

还有一件事:您现在可以在
@implementation
中声明实例变量,因此现在不需要在
@接口中泄漏任何实现细节。i、 e

@implementation MyClass
{
    NSString* myString;
}
// method definitions
@end

而且我很确定它也适用于分类请参阅下面的评论

我建议将所有内容声明为属性,并完全避免手动IVAR。手动创建IVAR没有真正的好处。在头文件
@interface
中声明公共属性,在.m文件的私有类扩展名中声明私有属性

JeremyP认为,在ARC下,访问器的内部使用仍然具有重要价值,尽管内存管理不再是一个重要问题。它确保KVO正常工作,更好地子类化,支持自定义setter(特别是对于
NSTimer
之类的东西),支持自定义getter(例如用于延迟实例化),等等。它非常容易出错,同时会混合使用访问器和IVAR。很容易忘记您需要以何种方式访问哪些内容。一致性是良好ObjC的标志

如果出于某种原因您必须声明ivar,那么您应该按照JeremyP的说明在
@implementation
块中进行声明


更新(2013年10月):

(来自使用Objective-C编程:封装数据):

大多数属性都有实例变量支持

一般来说,即使从对象自身的实现中访问对象的属性,也应该使用访问器方法或点语法进行属性访问,在这种情况下,应该使用
self

此规则的例外情况是在编写初始化、解除分配或自定义访问器方法时,如本节后面所述


我不认为这是同一个问题,但我更新了我的问题,希望让它更清楚。这不是真的。如果您在.m文件中声明了该属性怎么办?您可以完全隐藏该属性,但不能从m文件外部访问它,例如子类。@马丁:由于该属性是作为一对方法实现的,无论在哪里声明,它在运行时总是可用的。@Martin:您不知道哪一部分?属性真的是一个setter和getter方法,或者方法总是有效地公开?虽然使用
->
直接获取内部IVAR比setter更快,但这几乎永远都不是正确的答案。当你做这种优化的时候,几乎总是有一个更好的优化你应该做。这是一种非常危险的技术,不适用于一般用途。您不能将IVAR和属性添加到类别中,因为objc运行时只允许在类注册期间添加IVAR。在类注册到运行时后,您不能更改它的内存布局。但是,您可以将IVAR添加到类扩展中(密切相关,但不同于类别)@Jonathan Cichon:谢谢,刚刚尝试过,结果表明您对实例变量的理解是正确的,但对属性的理解是错误的。您可以添加属性,但不能合成属性。@JonathanCichon,类别中的非合成属性非常有用和常见。您只需编写一个自定义getter/setter。关于我最常用的这种技术,请看这篇博文:@Jonathan Cichon:恐怕这是对财产的误解。属性是API的一部分,实现由您决定,
@synthesis
只是通过添加一组标准的访问器来自动化最常见的实现模式之一。没有什么可以阻止您定义自己的不同访问器。KVO对于仅限于内部的东西并不重要。子类化也是如此。类实现的任何部分都不应泄漏,即使泄漏到子类。尽管这是良好OOP.KVO的标志(尽管偶尔会使用自我观察),但由于您经常需要访问私有属性(惰性实例化、线程安全等),并且使用它们既简单又便宜,因此您应该