8

可能重复:
可可objective-c 类中变量前面的下划线如何工作?


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

...
@interface myClass : parentClass {
className *variableName:
}

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

这导致 self.variableName 和 _variableName 成为 .m 中的两个不同变量。我需要的是:

...
@interface myClass : parentClass {
className *_variableName:
}

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

那么,在类'.m中,self.variableName和_variableName是等价的


在带有 ARC 的全新 Xcode 4.5+ 中,针对 iOS 5.0+ 项目,使用_variableNameoverself.variableName与旧式相比是否有明显的优势(运行时效率、速度等) @synthesize variableName

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

对我来说,仅self.variableName用于访问 iVar 似乎是最直接和最清楚您正在寻找哪个变量的方法。除了打字_vs.之外self.,使用 有没有优势_variableName

4

2 回答 2

17

我的理解是 Xcode 4.5+ 将创建一个等效于 self.variableName 的默认访问器“_variableName”,不使用“@synthesize variableName”的唯一原因是避免 iVar 和传入变量之间的混淆,对吗?

在这种情况下,_variableName不是访问器,它是由编译器自动生成并在自动 @synthesized setter 和 getter 中使用的 ivar。一般来说,最好尽可能使用访问器(即self.variableName),以便键值观察和绑定等内容适用于该属性。

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

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

2) Key-Value Notifications : 属性调用的默认设置器-willChangeValueForKey:and -didChangeValueForKey:,当属性改变时发出通知。如果使用绑定,这对于任何正确更新以及任何其他键值观察都是必要的。

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

从技术上讲,直接访问 ivar 比使用访问器要快,但是在极少数情况下它会产生显着的性能差异,并且可能是过早优化的情况。即使你不觉得你会立即使用上面列出的好处,最好还是使用访问器,这样如果你以后决定需要一些功能,你不必更改每个实例访问该变量(并可能在此过程中创建意外的新错误)。

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

通常,我尝试仅在 、 和属性的访问器中直接访问initivars dealloc。许多工程师都遵循这条经验法则,因为有时在访问器中发生的自定义内容可能会在对象init'ing 或dealloc'ing 时导致意外行为。例如,如果访问器中的任何内容导致您的对象发生某些事情,retain甚至release形成对它的归零弱引用,那么如果在dealloc.

于 2013-01-01T18:33:01.170 回答
5

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

@synthesize someName = _someName;

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

@synthesize someName = someSpecialName;

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

于 2013-01-01T17:56:13.537 回答