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