Naming convention in Objective C /C , start with “

2019-06-23 15:07发布

问题:

Something I see ppl define the variable like this:

b2World *_world;
b2Body *_body;
CCSprite *_ball;

instead of

b2World *world;
b2Body *body;
CCSprite *ball;

I familiar with the second one, but not the first one. So, I checked the Wikipedia about naming convention:

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).

So, is that any special meaning which is start with "_"?

The code I saw which using "_" to begin is here:

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

The wiki page.

回答1:

There's a long-standing convention among some Objective-C developers to prefix instance variables with an underscore. It can be helpful in several ways: one, it makes it easier to spot instance variables in a .m file; two, it relieves developers of having to come up with creative names for method parameters to avoid colliding with instance variable names; and three, as others have noted, it indicates that the instance variables are private, and therefore shouldn't be accessed willy nilly throughout the code.

In fact, I'd argue for avoiding accessing instance variables directly in methods other than accessors (getters and setters), -dealloc, and -init.... Not that you should never, ever use them anywhere else, but you should at least give it some thought before using an instance variable directly in other methods.



回答2:

It's really really helpful, but most people don't know why, and that's a shame. Apple uses underscores to separate the way other objects access a particular object's variables, and the way a particular object access its own variables. Now this may sound a little bit strange, but imagine the following: You probably all recognize the following compiler warning

.h
@property (nonatomic, retain, readonly) UITableView *tableView;

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

This will result in a compiler warning, because it does not know wether you reference to the local variable "tableView", or the instance variable. Therefore, Apple recommends you to add the following to the top of your @implementation.

@synthesize tableView = _tableView;

Now, when you reference to _tableView, the compiler knows that you mean the instance variable, and not the local one.

Also, this makes it a lot easier to understand the Garbage Collection in Obj-C, and to prevent making common mistakes.

For example, when doing the following:

@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;
}

Now, since you do not use the default setter (actually, you can't, because it's read-only) you need to retain the variable yourself. This is a lot easier to remember when you give every instance variable a prefix (so you know you need to retain it yourself).

So, basically, it's important to understand the difference between self.variable and (_)variable. (that is: self.variable maps to [self setVariable:...] and variable maps directly to your pointer.

Furthermore, when you add it as a private variable, like this:

@interface TSSomeObject : NSObject {
@private
    NSString *_privateTitle;
}
@end

The underscore prefix isn't really necessary, unless you may encounter local variables that have the same name. Besides that, again, it's also an easy way to remind you that it's a local pointer and that you need to retain (and release) the variable when you assign it to your object.

What is wrong is to create a property with a underscore prefix, like this:

@property (nonatomic, retain) NSString *_title;

That's really wrong, and I'm not even gonna explain why ;)


So yes! You should really use underscore prefixes, it makes your code a lot easier to read, and to interpret by the compiler! In Xcode 4, Apple even added these @synthesizes to the default templates.



回答3:

Usually they're used for variables that shouldn't be accessed outside the current file/module/namespace/whatever, in languages that don't support restricting access with something like a private keyword



回答4:

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingIvarsAndTypes.html#//apple_ref/doc/uid/20001284-1001757

Both by convention and recommendation in the above document, you should prefix ivars with an underscore.

Admittedly, it is in reference to explicitly set ivars for properties.

But the usage is the same, to indicate the usage of an ivar wherever it is seen.

I am however open to the possibility, that in that context, the use of an underscore prefixed ivar could signal to the user that they are doing something wrong. Meanwhile a postfixed underscore could be used for pure ivars that are meant to be accessed directly.

This blog has some good thoughts from an experienced practitioner and it recommends using prefixed underscores.

http://blog.bignerdranch.com/463-a-motivation-for-ivar-decorations/

Wether you choose to use prefixed underscores to decorate your own ivars, there is at least some evidence that some kind of decoration will help you avoid bugs. And prefix'd underscores are the most common decoration.



回答5:

Apple reserves names beginning with underscore for its own private ivars and methods. In Objective-C on any Apple platform, it is recommended that you do not prefix your identifiers with an underscore.

http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingMethods.html