Objective C / C中的命名约定,以“_”开头?

Naming convention in Objective C /C , start with “_”?

我看到ppl定义变量如下:

1
2
3
b2World *_world;
b2Body *_body;
CCSprite *_ball;

而不是

1
2
3
b2World *world;
b2Body *body;
CCSprite *ball;

我熟悉第二个,但不是第一个。所以,我查阅了维基百科关于命名约定的内容:

Names beginning with double underscore
or an underscore and a capital letter
are reserved for implementation
(compiler, standard library) and
should not be used (e.g. __reserved or
_Reserved).

那么,这是不是有什么特别的意义,从"uu"开始?

我看到的使用"u"开始的代码如下:

http://www.raywenderlich.com/457/intro-to-box2d-with-cocos2d-tutorial-bouncing-balls

维基页面。


在一些Objective-C开发人员中有一个长期的约定,即在实例变量前面加下划线。它可以从以下几个方面提供帮助:一,它使在.m文件中更容易地发现实例变量;二,它减轻了开发人员必须为方法参数提供创造性的名称以避免与实例变量名冲突;三,如其他人所说,它表明实例变量是私有的,因此不应在整个代码中随意访问。

实际上,我认为应该避免在访问器(getter和setter)、-dealloc-init...之外的方法中直接访问实例变量。并不是说您永远不应该在其他任何地方使用它们,但在直接在其他方法中使用实例变量之前,您至少应该考虑一下。


这真的很有帮助,但大多数人不知道为什么,这是一种耻辱。苹果使用下划线来分隔其他对象访问特定对象变量的方式,以及特定对象访问自己变量的方式。现在这听起来有点奇怪,但请想象一下:您可能都认识到下面的编译器警告

1
2
3
4
5
6
7
.h
@property (nonatomic, retain, readonly) UITableView *tableView;

.m
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [self loadSomethingElseForTableView:tableView];
}

这将导致编译器警告,因为它不知道您是否引用了本地变量"tableview"或实例变量。因此,苹果建议您在@implementation的顶部添加以下内容。

1
@synthesize tableView = _tableView;

现在,当您引用_tableView时,编译器知道您指的是实例变量,而不是本地变量。

而且,这使得理解obj-c中的垃圾收集变得容易得多,并防止犯常见的错误。

例如,执行以下操作时:

1
2
3
4
5
6
7
8
9
10
11
@property (nonatomic, retain, readonly) NSString *title;

- (id)initWithTitle:(NSString *)title {
    if ((self = [super init])) {
        self.title = title; // Is not possible, since it's read only.
        title = title; // Is not possible, since it's the same (local) variable.
        // Changing the method to initWithTitle:(NSString *)aTitle;
        title = aTitle;
    }
    return self;
}

现在,由于您不使用默认的setter(实际上,您不能这样做,因为它是只读的),所以您需要自己保留变量。当您给每个实例变量一个前缀时(这样您就知道需要自己保留前缀),这就更容易记住了。

所以,基本上,了解self.variable和(_variable之间的区别是很重要的。(即:self.variable映射到[self setVariable:...]variable直接映射到指针。

此外,当您将其添加为私有变量时,如下所示:

1
2
3
4
5
@interface TSSomeObject : NSObject {
@private
    NSString *_privateTitle;
}
@end

除非您可能遇到具有相同名称的局部变量,否则下划线前缀实际上不是必需的。除此之外,这也是一种简单的方法来提醒您,它是一个本地指针,当您将变量分配给对象时,需要保留(和释放)它。

错误是使用下划线前缀创建属性,如下所示:

1
@property (nonatomic, retain) NSString *_title;

这真的是错误的,我甚至都不想解释为什么;)

所以是的!你真的应该使用下划线前缀,它使你的代码更容易阅读,也更容易被编译器解释!在Xcode4中,苹果甚至将这些@synthesize添加到默认模板中。


https://developer.apple.com/library/mac/documentation/cocoa/conceptive/codingguidelines/articles/namingivarsandtypes.html//apple-ref/doc/uid/20001284-1001757

根据上述文件中的惯例和建议,您应该在ivar前面加下划线。

诚然,它是指为属性显式设置ivar。

但是用法是相同的,表示在任何地方都可以看到ivar的用法。

然而,我愿意接受这样的可能性:在这种情况下,使用带下划线前缀的ivar可能会向用户发出信号,表明他们做错了什么。同时,一个固定后的下划线可以用于纯ivar,这是为了直接访问。

这个博客有一些来自经验丰富的从业者的好想法,它建议使用带前缀的下划线。

http://blog.bignerdranch.com/463-a-motivity-for-ivar-decorations/装饰/

无论您选择使用带前缀的下划线来装饰自己的ivar,至少有一些证据表明某种装饰可以帮助您避免错误。前缀的下划线是最常见的装饰。


通常,它们用于不应在当前文件/模块/名称空间/任何内容之外访问的变量,使用的语言不支持使用诸如private关键字之类的限制访问。


苹果保留了以下划线开头的名称,用于自己的私有ivar和方法。在任何Apple平台上的Objective-C中,建议您不要在标识符前面加下划线。

http://developer.apple.com/mac/library/documentation/cocoa/conceptive/codingguidelines/articles/namingmethods.html