在可可目标 -c 类中,变量前面的下划线是如何工作的?

我在一些 iPhone 示例中看到,属性在变量前使用了 underscore _。有人知道这意味着什么吗?或者它是如何工作的?

我使用的接口文件看起来像:

@interface MissionCell : UITableViewCell {
Mission *_mission;
UILabel *_missionName;
}


@property (nonatomic, retain) UILabel *missionName;


- (Mission *)mission;

我不太清楚上面提到的是什么,但是当我设置任务名称的时候:

aMission.missionName = missionName;

我得到了一个错误:

在非结构或联合中请求成员“ misonName”

52696 次浏览

这并不意味着什么,只是一些人用来区分成员变量和局部变量的一个惯例。

至于错误,听起来好像 aMission 的类型是错误的。它的声明是什么?

如果您为 ivar 使用下划线前缀(这只是一个常见的约定,但是很有用) ,那么您需要做一件额外的事情,以便自动生成的访问器(对于属性)知道使用哪个 ivar。具体来说,在您的实现文件中,您的 synthesize应该如下所示:

@synthesize missionName = _missionName;

更一般地说,这是:

@synthesize propertyName = _ivarName;

这只是可读性的一个约定,对编译器没有什么特别的作用。您将看到人们在私有实例变量和方法名称上使用它。苹果实际上建议不要使用下划线(如果你不小心的话,你可能会在你的超类中覆盖一些东西) ,但是你不应该因为忽略这个建议而感到内疚。:)

我所看到的唯一有用的目的是区分局部变量和成员变量,如上所述,但这不是一个必要的约定。当与@属性配对时,它会增加合成语句的冗长度—— @synthesize missionName = _missionName;,而且处处都很难看。

不要使用下划线,只要在不冲突的方法中使用描述性变量名即可。当他们必须冲突时,方法中的变量名应该使用下划线,而不是可能被多个方法使用的成员变量。唯一有用的地方是在 setter 或 init 方法中。此外,它还将使@综合语句更加简洁。

-(void)setMyString:(NSString*)_myString
{
myString = _myString;
}

编辑: 通过最新的自动合成编译器特性,我现在使用 ivar 的下划线(在极少数情况下,我需要使用 ivar 来匹配自动合成的功能。

使用下划线不仅可以在不使用 自我,记住语法的情况下解析 ivar,还可以让代码更具可读性,因为你知道什么时候变量是 ivar (因为它的下划线前缀)或成员参数(没有下划线)。

例如:

- (void) displayImage: (UIImage *) image {


if (image != nil) {
// Display the passed image...
[_imageView setImage: image];
} else {
// fall back on the default image...
[_imageView setImage: _image];
}
}

这似乎是关于 self. variableName vs _ variablename 问题的“主”项。让我大吃一惊的是。我有:

...
@interface myClass : parentClass {
className *variableName;    // Note lack of _
}


@property (strong, nonatomic) className  *variableName;
...

这导致 self. variableName 和 _ variableName 成为. m 中两个不同的变量:

...
@interface myClass : parentClass {
className *_variableName;    // Note presence of _
}


@property (strong, nonatomic) className  *variableName;
...

然后,在类’. m 中,self. variableName 和 _ variableName 是等价的。

我仍然不清楚的是,为什么许多例子仍然有效,即使很难做到这一点。

这只是合成性能的变数命名原则。

当您在. m 文件中合成变量时,Xcode 将自动提供 you _ variable 智能。

不使用下划线,你可以使用 self. variable name,或者你可以合成变量使用没有下划线的变量或出口。

其他答案中缺少的是,使用 _variable可以防止您心不在焉地键入 variable并访问 ivar 而不是(假定是有意的)属性。

编译器将强制您使用 self.variable_variable。使用下划线使得不可能键入 variable,这减少了程序员错误。

- (void)fooMethod {


// ERROR - "Use of undeclared identifier 'foo', did you mean '_foo'?"
foo = @1;


// So instead you must specifically choose to use the property or the ivar:


// Property
self.foo = @1;


// Ivar
_foo = @1;


}