XCode 模板中的 ivars 前缀为一或两个下划线

Posted

技术标签:

【中文标题】XCode 模板中的 ivars 前缀为一或两个下划线【英文标题】:ivars in XCode templates prefixed with one or two underscores 【发布时间】:2012-04-21 11:51:25 【问题描述】:

有人知道为什么在 XCode 模板中(至少在 XCode 4.3.2 中)有一些 ivars 前缀有两个下划线,而一些只有一个?

例如 Master-Detail 应用程序模板包含文件 MasterViewController.m,可以在其中找到:

@synthesize detailViewController = _detailViewController;
@synthesize fetchedResultsController = __fetchedResultsController;
@synthesize managedObjectContext = __managedObjectContext;

谢谢。

【问题讨论】:

【参考方案1】:

这是一小罐​​虫子。

@synthesize 中使用下划线,主要用于区分实例变量和访问器名称。这很重要,特别是如果您不仅仅访问访问器中的变量(例如,延迟初始化)。如果它们同名,您可以轻松键入“foo”并获取实例变量,而您的意思是调用访问器方法的“self.foo”。所以,这就是在这种情况下使用下划线的原因。

现在,Apple 表示我们不应该在私有 方法 名称中使用前导下划线。他们使用该约定作为其私有方法名称,您可能会无意中覆盖其中一个基类方法。那会很糟糕,尤其是因为您无法在编译时捕捉到它。

但是,他们说私有实例变量可以使用下划线。事实上,作为一个例子,他们说在合成属性时为 ivars 使用前导下划线是完全可以的(并且建议)。

现在,问题来了。他们还为私有实例变量使用单个前导下划线。所以,如果你有相同的名字,你可能会发生冲突。要看到这一点,在视图控制器方法的实现中,他们“_”并查看代码完成会抛出什么问题。

那么,为什么他们不反对这种命名习惯呢?因为冲突是在编译时捕获的。您不能有两个具有相同名称的实例变量。如果你尝试这样做,你会得到一个错误。

现在,为什么他们的代码模板会生成带有双下划线的名称?我不知道。 “实现”实际上保留了前导双下划线(后跟大写字母),但我们看到像 __block 这样的 ObjC 添加。

为了我的钱,我避免使用前导双下划线。 Apple 可以在生成的代码中为所欲为。 FWIW,他们为 ARC 生成的一些代码仍然引用旧的非 ARC 关键字,所以我不会把他们生成的代码当作福音。 FWIW,我肯定不会保留他们为 Core Data 生成的代码。至少,您应该更改(在 managedObjectContext 访问器方法中):

__managedObjectContext = [[NSManagedObjectContext alloc] init];

__managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

顺便说一句,我看到人们使用美元符号作为前导或尾随字符作为他们的私有合成名称。

@synthesize foo = $foo;
@synthesize bar = bar$;

我已经编写 C/C++ 超过 25 年了,但我对 ObjC 还很陌生,它有其自身的复杂性。所以,我不是语言律师。我什至不是律师助理。我所知道的是它似乎是合法的——它适用于我尝试过的所有东西,但我不能肯定地说美元符号不应该用于其他用途。 Xcode 语法高亮不喜欢它(它不会用变量名的其余部分为它着色)。

我希望这足以回答您的问题,尽管它可能只是促使您提出更多问题...

【讨论】:

感谢乔迪的回答 - 我真的很感激,尽管我已经知道了其中的大部分内容。我只是好奇为什么 Apple 对某些 ivars 使用 '_' 和其他一些 '__'。当我获得所需的声誉时,我会将您的答案标记为有用。 这很奇怪——$ 不应该是标识符的合法字符(AFAIK,规则与“普通”C 相同)。回复:__block 和其他存储限定符——这些现在实际上是实现的一部分(clang/Apple 的 LLVM),所以双下划线在这种情况下是合适的。不错的答案! 按照承诺+1。顺便提一句。我注意到这不是我最初写的 MasterDetail 模板的情况 - 他们也在其他模板和类中使用这种差异(甚至在 AppDelegate 中)。

以上是关于XCode 模板中的 ivars 前缀为一或两个下划线的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 4.5 中@property 和 ivar 的区别

iOS自动@synthesize而不创建ivar

Xcode 6 中的 iCloud 容器名称前缀更改

前缀标头中的 XCode 存档错误

dealloc 方法从 Xcode 4 中的 ViewController 实现文件模板中消失了吗?

模拟测试46