Objective-C中的单个下划线显然是为Apple的"内部"使用保留的(并且在Apple声明之前可用于私有实例变量).但是为什么他们会在他们的SQLiteBooks示例中为iPhone 使用双 -underscore呢?请参阅从MasterViewController.m获取的此片段:
+ (EditingViewController *)editingViewController { // Instantiate the editing view controller if necessary. if (__editingViewController == nil) { __editingViewController = [[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil]; } return __editingViewController; }
在这个论坛上提到了双重下划线,因为它与C有关 - 它是"compier的内部使用".我想我不知道这在这种情况下是如何适用的.
我在我的应用程序中需要一个ViewController,它的行为与SQLiteBooks示例项目中的一样,但是这个双下划线让我感到困惑.
C编译器和Objective-C编译器都不会将带有前导下划线的变量名称与任何其他变量名称区别对待.单个或双前导下划线只是一个约定,有效地形成一个命名空间,就像NS
Cocoa类中使用的前缀一样NSString
.
查看SQLiteBooks代码,MasterViewController.m
定义此静态全局变量:
// Manage the editing view controller from this class so it can be easily accessed from both the detail and add controllers. static EditingViewController *__editingViewController = nil;
所以我的猜测是SQLiteBooks的作者使用双前导下划线来表示全局变量.
C编译器(以及扩展名Objective-C)保留以两个下划线和大写字母开头的名称供编译器供应商使用,为它们提供一个保留的命名空间,用于全局变量和用于实现标准库的函数,或引入新的非- 标准关键字__block
.
虽然SQLiteBooks代码在技术上是有效的,但在我看来,它很容易与保留的命名空间混淆.如果您确实重用了该代码,我建议重命名该变量(Xcode有一个非常好的重命名重构,它将自动为您执行).
对于编译器,下划线被视为任何字母字符.但更常见的是,下划线通常由语言扩展或大型库使用,以避免与用户代码冲突.
使用下划线是有问题的,因为许多组尝试使用下划线的特定组合来保留每个名称.
Apple传统上使用单个下划线前缀来表示私有实例变量(面向对象语言中的常见样式).这意味着每个人都应该在他们的ivars前加下划线,直到Apple指出在你的代码中使用下划线可能会与Cocoa产生冲突,如果Apple决定改变他们的标题,也许你不应该.因此,下划线前缀已成为"不建议"的编码实践.
在C和C衍生语言中,任何前后都有双下划线的单词都是非标准语言扩展.查看Apple的扩展名,如__attribute__
尾随下划线通常加入作为原始名称(特别是当编译器是多遍)的编译器或调试名称错位版本,并且通常避免使这些名称保持清楚地从原稿不同.Google使用下划线为其Objective-C本地实例变量添加后缀,以避免与Apple的下划线冲突.
我的建议:不要使用下划线.您不应该使用与实例变量同名的局部变量(这只是令人困惑).唯一潜在的冲突是setter方法的参数和相应的实例变量之间 - 你或许应该前缀以小写的"a"参数,"新"(或类似),因为这明确指出该参数是传入值但还不是"价值".