关于objective c:self.variable Name vs. _variableName vs. @sysnthesize variable Name

self.variableName vs. _variableName vs. @sysnthesize variableName

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
How does an underscore in front of a variable in a cocoa objective-c class work?

注意:对于那些到处挖掘试图理解这一点的人,我找到了我困惑的根源。在H中,我有:

1
2
3
4
5
6
7
...
@interface myClass : parentClass {
className *variableName:
}

@property (strong, nonatomic) className  *variableName;
...

这导致self.variablename和_variablename在.m中是两个不同的变量。我需要的是:

1
2
3
4
5
6
7
...
@interface myClass : parentClass {
className *_variableName:
}

@property (strong, nonatomic) className  *variableName;
...

然后,在类".m"中,self.variablename和_variablename是等效的。

在全新的Xcode 4.5+,带有ARC,面向iOS 5.0+项目中,使用_variableName比使用self.variableName比使用旧式@synthesize variableName有明显的优势吗?

我的理解是xcode 4.5+将创建一个默认的访问器_variableName,相当于self.variableName,不使用@synthesize variableName的唯一原因是为了避免ivar和传入变量之间的混淆,对吗?

对我来说,仅仅使用self.variableName访问一个ivar似乎是最直接和最清晰的关于您要寻找的变量。除了输入_self.以外,使用_variableName有什么好处吗?


My understanding is that Xcode 4.5+ will create a default accessor"_variableName" that is equivalent to self.variableName and the only reasons not to use"@synthesize variableName" is to avoid confusion between iVars and passed-in variables, correct?

在这种情况下,_variableName不是访问器,它是一个由编译器自动生成的ivar,用于自动@synthed setters和getter。一般认为,最好尽可能使用访问器(即self.variableName),以便诸如键值观察和绑定之类的东西可以用于该属性。

当您直接访问一个IVAR时,它是通过直接内存访问来访问的,就像您访问结构中的数据一样。它只是获取拥有IVAR的对象的指针,偏移内存地址,并尝试读取或写入该位置的内存。使用点表示法(self.variableName调用accessor方法来设置或获取该属性,并可以一路执行许多不同的操作,例如:

1)锁定:如果该属性将在多个线程中使用,并且是一个atomic属性,运行时将自动进行一些锁定,以确保该属性不会同时从多个线程访问。如果您的对象不打算在多个线程上使用,您可以在属性声明中给出nonatomic提示,以便合成的访问器跳过锁定。

2)键值通知:属性的默认设置者调用-willChangeValueForKey:-didChangeValueForKey:,当属性发生变化时发出通知。如果使用绑定,则需要对任何内容进行正确更新,并且需要对任何其他键值进行观察。

3)自定义访问器行为:如果您最终编写自己的setter和getter,那么您在其中实现的任何自定义内容。

从技术上讲,直接访问IVAR比使用访问器更快,但是很少有情况下它会造成显著的性能差异,并且可能是过早优化的情况。即使您不觉得马上就可以使用上面列出的好处,但最好还是使用访问器,这样,如果您稍后决定需要某些功能,您就不必更改访问该变量的每个实例(并且可能会在过程中创建意外的新错误)。

此外,如果您直接访问ivar并最终将类重构为类别或子类,则会变得混乱,因为您通常必须将ivar声明为@protected变量。如果您使用的是访问器,则不必这样做。

一般来说,我只尝试直接访问initdealloc中的ivar,以及财产的访问器。很多工程师都遵循这条经验法则,因为有时当对象是initdealloc时,在访问器中发生的自定义事件会导致意外行为。例如,如果访问器中的任何内容导致了对象的retainrelease,甚至形成了对它的零弱引用,那么如果在dealloc中使用,它将导致崩溃。


在最新的xcode中,@synthesize是可选的。默认情况下,省略@synthesize与写入相同。

1
@synthesize someName = _someName;

使用@synthesize的唯一原因是重命名为存储属性值而创建的实例变量,例如

1
@synthesize someName = someSpecialName;

当您使用self.variableName访问变量时,您将访问一个属性,这是一个为您访问实例变量的简短方法。虽然方法调度速度非常快,但它可以为您执行额外的服务,例如同步对变量的访问(当您在属性声明中指定atomic或不指定nonatomic时就是这种情况)。在这种情况下,通过self.variableName的访问会稍微慢一些。如果在一个紧密的循环中完成,这可能会产生影响。这就是为什么您有时希望使用_variableName直接访问底层实例变量的原因。