Naming Conventions for Instance Variables and Properties

Here is some information that you might find useful on how to name various elements of your code, which hopefully will allow greater clarity in your projects and understanding of Objective-C.  I’ve not come across this information anywhere else, just what I’ve gleaned from various places within the Apple documentation.  It took me a while to get my head around how this worked and made understanding the example code harder work without this grounding.

Name Instance Variables with Underscore

When adding instance variables to a class, always prefix them with underscore (_) so that its clear in the code what scope a variable has.  You should know:

  • Instance variables are protected by default, meaning that they can only be accessed directly by the current class and any sub-classes.
  • Instance variables of the current class (or parent class) can be directly referenced without the use of self, so for readability its good practice to distinguish them from variables in the local scope.

@interface MyObject : NSObject {
    NSArray *_arrayOfThings;
}

-(void) myMethod;
@end

@implementation MyObject

-(void) myMethod {
    for (id item in _arrayOfThings) {
        // do something ...
    }
}
@end

In the above example, the instance variable is being directly accessed.  The underscore helps to indicate that the variable belongs to the instance, and is not a parameter or local variable.  You can of course use other naming conventions that suit you and your experience.  Some people like to use ‘m’ as a prefix on ‘member variables’, so the above becomes mArrayOfThings.

Avoiding the ‘Local Declaration of <var> Hides Instance Variable’ Compiler Warning

The situation where I found this problematic was in choosing instance variable names, then finding a conflict with delegate methods.  The SDK examples do this all the time without clarification, which caused me much confusion.  Consider this:




@interface MyTableViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
    UITableView *tableView;
}

@property (nonatomic,retain) IBOutlet UITableView *tableView;

@end

@implementation MyTableViewController

@synthesize tableView;

-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // parameter 'tableView' now masks the instance variable 'tableView'

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: @"ident"];

    // The above line will cause a compiler warning highlighting the masking

    //...
}

@end

The above is fairly common code, defining an instance variable and property as an outlet to an object in Interface Builder.  The obvious choice of the instance variable name then causes problems with masking of parameters in the delegate methods.

Properties Do Not Have to Match Instance Variables

One thing to get your head around is that @property is a hint that enables the ‘dot’ notation when accessing instance variables (i.e. self.myInstanceVariable).  That alone provides the shorthand dot notation.  It assumes that there will be getter/setter methods called myInstanceVariable and setMyInstanceVariable respectively, normally generated by the @synthesize statement.

@synthesize does the magic of automatically creating getters/setters and assumes that the instance variable uses the same name, but you are able to redirect the @synthesize within the statement, so:

@synthesize myInstanceVariable = _myInstanceVariable;

allows you to declare the instance variable with an underscore, and the property without.

@interface MyTableViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
    UITableView *_tableView;
}

@property (nonatomic,retain) IBOutlet UITableView *tableView;

@end

@implementation MyTableViewController

@synthesize tableView = _tableView;

-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    // The following line references the parameter 'tableView'

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: @"ident"];

    // The following line references the property of the class (and thus indirectly the instance variable)

    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier: @"ident"];

    // The following line references the instance variable directly (but should be avoided)

    UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier: @"ident"];

    //...
}

@end




2 thoughts on “Naming Conventions for Instance Variables and Properties

  1. Humberto

    Hello.

    Thanks for writing this article. Very useful and clear for those who want a deep understanding about Objective-C.

    But… I have a question…

    On internet, you can find tons of objective-c codes, and I noticed people use both ways… (self.tableView & _tableView)

    According to the Apples convention… what is the “must be” for this example?

    self.tableView or _tableView?

    Thanks for your comments.

    Reply
  2. Dave Post author

    I’m not sure there is any ‘standard’ to follow, probably more one of personal preference. The underscore convention can be good to clearly document variables that are in the wider scope, not just within the method, to be confused with parameter variables, and is shorter form than referencing via self.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *