【问题标题】:self.variableName vs. _variableName vs. @sysnthesize variableName [duplicate]self.variableName vs. _variableName vs. @sysnthesize variableName [重复]
【发布时间】:2012-12-16 06:27:34
【问题描述】:

可能重复:
How does an underscore in front of a variable in a cocoa objective-c class work?


注意:对于那些四处挖掘试图理解这一点的人,我找出了我困惑的根源。在 .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+ 项目,使用 _variableName 与旧式相比,使用 _variableName 是否有明显优势(运行时效率、速度等) @synthesize variableName?

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

对我来说,仅使用self.variableName 访问 iVar 似乎是最直接和最清楚您要查找的变量的方法。除了输入_self. 之外,使用_variableName 有什么优势吗?

【问题讨论】:

标签: objective-c synthesize


【解决方案1】:

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

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

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

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

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

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

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

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

一般来说,我尝试只在initdealloc 和属性的访问器中直接访问ivars。许多工程师遵循这条经验法则,因为有时访问器中发生的自定义内容可能会导致意外行为,而对象是init'ing 或dealloc'ing。例如,如果访问器中的任何内容导致 retainrelease 您的对象发生某些事情,甚至形成对它的归零弱引用,如果在 dealloc 中使用,则会导致崩溃。

【讨论】:

    【解决方案2】:

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

    @synthesize someName = _someName;
    

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

    @synthesize someName = someSpecialName;
    

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

    【讨论】:

    • 只是为了迂腐,根据您的回复和@eyebrowsoffire,_variableName 可能更快,但 self.variableName 更安全?
    • @RayatERISCorp "Safer" 在此上下文中定义不足,但如果您打算以同步方式使用属性(即atomic),那么答案是肯定的,它更安全。事实上,另一种方式(即直接使用_variableName)在没有额外锁定的情况下根本行不通。
    • 明白了。 “更安全”是指“不太可能在我的代码中触发一些意外错误,这将使我调试的时间比我应该做的要长得多,因为使用 _variableName 不会自动启动 self.variableName 所做的某些操作。”
    猜你喜欢
    • 2012-09-17
    • 2011-07-07
    • 2011-03-29
    • 2011-05-18
    • 2018-08-01
    • 2015-11-15
    • 2020-01-14
    • 2011-06-16
    相关资源
    最近更新 更多