3

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

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

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

谢谢。

4

1 回答 1

5

这是一小罐​​虫子。

@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 语法高亮不喜欢它(它不会用变量名的其余部分对其进行着色)。

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

于 2012-04-21T13:08:29.483 回答