Skip to main content

Prefixing property names with an underscore in Objective C



I've always avoided underscores in my variable names, perhaps because its just not what was done back in my learning Java in college days. So when I define a property in Objective C this is what I naturally do.







//in the header

@interface Whatever

{

NSString *myStringPorperty

}



@property (nonatomic, copy) NSString *myStringProperty;



//in the implementation

@synthesize myStringProperty;







But in almost every example it is done like







//in the header

@interface Whatever

{

NSString *_myStringPorperty

}



@property (nonatomic, copy) NSString *myStringProperty;



//in the implementation

@synthesize myStringProperty = _myStringProperty;







Should I get over my aversion to the underscore because that is the one way it should be done, is there a good reason for this style being the preferred one?


Comments

  1. Current suggested Objective-C 2.0 practice is to use the same name for the ivar as the property. You can optionally assign a different ivar in the @property declaration, but the fact that by default, synthesized accessors for a property will access the ivar with the same name as the property indicates that's the pattern they expect you to follow.

    No matter what, since objects still have to send messages to themselves to access properties, it's hard to confuse when you're accessing a property or when you're accessing its backing ivar directly, though using the 2.0 dot access to properties does make it more possible. Using the standard message passing syntax makes intent more explicit, IMO.

    @interface Foo : NSObject {
    NSNumber *bar;
    }
    @property(readwrite, retain) NSNumber * bar
    @end

    @implementation Foo
    @synthesize bar

    -(void) baz {
    NSNumber *numberOne = [NSNumber numberWithInt: 1];
    //Both set the value of bar through either the your custom or the synthesized setter method
    [self setBar:numberOne];
    self.bar = numberOne;

    //Both get the value of bar through your synthesized or your custom accessor method
    NSNumber *fooBar = [self bar];
    fooBar = self.bar;

    //Both manipulate the bar ivar directly
    bar = numberOne;
    fooBar = bar;
    }
    @end

    ReplyDelete
  2. I always use underscores. It creates a clear distinction between local variables and instance variables. It also avoids compiler warnings in the following situation:

    @interface MyClass
    {
    NSString *name
    }

    @property (nonatomic, copy) NSString *name;

    - (id) initWithName:(NSString *) name;
    @end

    @implementation MyClass

    @synthesize name;

    // The following method will result in a compiler warning
    // (parameter name same as ivar name)
    - (id) initWithName:(NSString *) name {
    if (self = [super init]) {
    self.name = name;
    }

    return self;
    }

    @end


    EDIT:

    After having to endure downvotes and reading through the comments, let me try to make my point:

    Apple recommends that ivars have the same name as their property. Apple also recommends that properties start with a lowercase letter. And Apple also recommends that local variables start with a lowercase letter.

    Now you have a problem, because when you read a piece of code, and you see a variable being used, you cant' tell by the naming convention if this variable is an ivar or a local variable. That sucks. The solution is to have different naming conventions for ivars and local variables. That's just plain common sense.

    The way you implement this naming convention is irrelevant. If you really want, you can simply append "_WOOHAHA" to the ivar names. I don't care (but maybe others will). The thing is that people who know what they're doing have decided to go with the "underscore prefix" for ivars. IMHO, they made the right decision, even if their own company recommends something else. (the developers I'm talking about are the people writing some major Apple frameworks and the .NET Framework classes)

    In the end, code quality is more important than following a stupid rule that isn't even followed by the people preaching it.



    Another remark about the code you've shown: never use retain on string properties. You should use copy instead.

    For more info about copy/retain on properties, see:

    http://stackoverflow.com/questions/387959/nsstring-property-copy-or-retain

    ReplyDelete
  3. Apple reserves selectors beginning with underscore for their own "private" methods and that would include properties. I don't think they reserve _ for ivar names though.

    Personally, I would steer clear of using underscore to start any kind of variable name. It's an opaque convention. What if somebody else uses underscore for locals and no underscore for instance variables? What if you accidentally omit the underscore in a method where you have a local defined with the same name?

    It's much better to make your local names different from your ivar names. For example in a setter you might use newName or neWValue.

    ReplyDelete
  4. It is purely a style issue.

    I don't know which examples use the underscored ivar style. The official Apple examples (e.g. CryptoExercise) do not prefix the ivars with _.

    ReplyDelete
  5. The KVC part of the runtime expects either a name or _name ivar when using valueForKey: on an object when it cant find a message to retrieve that variable. see http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/SearchImplementation.html

    If the runtime bothers to search for _name and the apple documentation mentions the _name first there might be a good reason for this. Let's take a look at some SDK classes: UINavigationBar.h this class has underscores in front of all ivars, UIView too... the list goes on. Well maybe it is that way with the new fangled iOS SDK and good ole NS* classes don't do thinges that way... wrong; they use the underscore as well in the header files.

    Apple uses the underscore in private API messages as well as ivars. I can't understand why their examples do not push this behavior especially when the runtime bothers to have this so called "naming convention" hard coded into the variable search path. It would be nice to see some consistency.

    Just a note, there is a strict naming scheme you have to follow to be KVC compliant; the link above helps you to conform to this to use this handy feature of the runtime.

    ReplyDelete
  6. I will just point out that a new navigation project using core data uses trailing underscores by default and makes the variables private.

    @interface MyTestAppDelegate : NSObject <UIApplicationDelegate> {

    UIWindow *window;
    UINavigationController *navigationController;

    @private
    NSManagedObjectContext *managedObjectContext_;
    NSManagedObjectModel *managedObjectModel_;
    NSPersistentStoreCoordinator *persistentStoreCoordinator_;
    }

    @interface RootViewController : UITableViewController <NSFetchedResultsControllerDelegate> {

    @private
    NSFetchedResultsController *fetchedResultsController_;
    NSManagedObjectContext *managedObjectContext_;
    }

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex