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有什么好处吗?
- 另外还有16个:stackoverflow.com/q/5582448 stackoverflow.com/q/6049269 stackoverflow.com/q/2371489 stackoverflow.com/q/7174277 stackoverflow.com/q/5659156 stackoverflow.com/q/837559 stackoverflow.com/q/6146244 stackoverflow.com/q/10651535 stackoverflow.com/q/6124109 stackoverflow.com/q/8145373 stackoverflow.com/q/3521254 stackoverflow.com/Q/6064283 stackoverflow.com/Q/9696359 stackoverflow.com/Q/5521499 stackoverflow.com/Q/5466496 stackoverflow.com/Q/2114587
- 我的错。我不想搜索拼写出来的"下划线"。也就是说,抽查了一些潜在的dup,我没有看到任何/新手证明提到键值观察、绑定和线程安全访问(atomic)的潜在问题(如果使用变量名与self.variablename)。其中一个(4088801)提到了一个潜在的问题,如果在variablename中引用的对象是共享的,建议使用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变量。如果您使用的是访问器,则不必这样做。
一般来说,我只尝试直接访问init、dealloc中的ivar,以及财产的访问器。很多工程师都遵循这条经验法则,因为有时当对象是init或dealloc时,在访问器中发生的自定义事件会导致意外行为。例如,如果访问器中的任何内容导致了对象的retain或release,甚至形成了对它的零弱引用,那么如果在dealloc中使用,它将导致崩溃。
在最新的xcode中,@synthesize是可选的。默认情况下,省略@synthesize与写入相同。
1
| @synthesize someName = _someName; |
使用@synthesize的唯一原因是重命名为存储属性值而创建的实例变量,例如
1
| @synthesize someName = someSpecialName; |
当您使用self.variableName访问变量时,您将访问一个属性,这是一个为您访问实例变量的简短方法。虽然方法调度速度非常快,但它可以为您执行额外的服务,例如同步对变量的访问(当您在属性声明中指定atomic或不指定nonatomic时就是这种情况)。在这种情况下,通过self.variableName的访问会稍微慢一些。如果在一个紧密的循环中完成,这可能会产生影响。这就是为什么您有时希望使用_variableName直接访问底层实例变量的原因。
- 只是为了学究一点,根据你的回答,@wearks soffire,@u variablename,可能更快,但self.variablename更安全?
- @在这种情况下,Rayateriscorp的"安全性"定义不充分,但如果您打算以同步方式使用某个属性(即,它是atomic),那么答案是"是",它更安全。事实上,另一种方式(即直接使用_variableName)在没有附加锁定的情况下无法工作。
- 抓住了。"更安全"的意思是"不太可能在我的代码中触发一些意想不到的错误,这些错误会使我的调试时间比本应的长得多,因为使用变量名不会自动启动self.variablename所做的某些操作。"