为什么Xcode会自动创建带下划线的变量?

4
在最新版本的Xcode(dp-4)中,使用retain,nonatomic声明变量时,为什么要在变量名前加下划线?这样做是否会创建某种类型安全性?
例如,我创建了一个属性:
@property (retain, nonatomic) IBOutlet UILabel *name;

除非我在dealloc内部更改变量以不含下划线的形式,否则我必须执行以下操作:

@synthesize name = _name;

为什么会这样呢?

我认为这只是另一种让你知道变量是属性并且不会将其与局部变量混淆的方式 - 但我可能完全错了,这只是我一直以来的看法...无论苹果想让我做什么,我都会去做 :P - RyanG
所有的@property都是这样工作的。我认为这只是一种编码规范,让你更容易地找到你的类属性所在的位置。 - Pedro Vieira
2个回答

7

马克·达利普尔比我聪明得多,他在Big Nerd Ranch写了一篇关于这个主题的博客文章链接。底线是下划线是一个好主意。为了防止链接失效,我将在此总结他的帖子,但如果可能的话,您应该阅读他的帖子而不是我的摘要。

他在强制显式调用@synthesize时撰写了这篇文章。他提倡使用以下代码:

// soapbubble.m
@synthesize viscosity = _viscosity;
@synthesize detergentBrand = _detergentBrand;

这些天,Xcode自动且隐式地包含了@synthesize。而且它使用了前置下划线,因此显然苹果的工程师们同意Mark的观点。
他的第一个原因是风格上的。它使您可以轻松地看到哪些变量是本地的,哪些是setter中的参数:
- (void) setPonyName: (NSString *) ponyName {
    [_ponyName autorelease];
    _ponyName = [ponyName copy];
}

这是一个预-ARC setter,所以现在这个方法完全不必要了,但是如果setter执行的操作比仅释放和分配值更复杂,它仍然适用。

他的第二个原因(我认为更重要的原因)是消除了一类非常难以追踪的错误。

这段代码:

self.ponyName = @"Mikey";

等同于:

[self setPonyName: @"Mikey"];

没有添加下划线,这段代码也是有效的:
ponyName = @"Mikey";

但它不调用setter,因此setter中的任何副作用都不会发生。同样,在setter除了更改局部变量的值之外还执行额外工作的情况下,这可能会引起大问题。使用前缀下划线,该行将导致编译错误。您必须非常明确地想要设置一个本地变量:
_ponyName = @"Mikey";

作为一个认真负责的程序员,你会包含一条注释,解释为什么要执行这个不规则的操作。


1
在你的 @synthesize name = _name 中,_name 只是由 Xcode 自动创建的变量名。这是因为 @synthesize 只会创建 setter 和 getter,如果你不使用 _name,它将采用你的属性名,即 name(在这种情况下),最终导致应用程序中的错误。_name 只是一种命名约定。你可以使用任何变量名来代替 _name。这样,@synthesize 将在其实现中使用该变量名。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接