I recently started to develop an iPhone App. Coming from C#, Objective-C has some traps for me. I dont’t understand what happened in the following snippet:
@interface RootViewController : UITableViewController {
NSString *simpleProperty;
NSString *propertyWithUnderscoreIvar;
}
@property (nonatomic, retain) NSString *simpleProperty;
@property (nonatomic, retain) NSString *propertyWithUnderscoreIvar;
@end
@implementation RootViewController
@synthesize simpleProperty;
@synthesize propertyWithUnderscoreIvar = _propertyWithUnderscoreIvar;
- (NSString *)simpleProperty {
return @"Simple property value";
}
- (NSString *)propertyWithUnderscoreIvar {
return @"Property with underscore value";
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog([NSString stringWithFormat:@"%i %@", 1, simpleProperty]);
// --> 1 (null)
NSLog([NSString stringWithFormat:@"%i %@", 2, propertyWithUnderscoreIvar]);
// --> 2 (null)
NSLog([NSString stringWithFormat:@"%i %@", 3, _propertyWithUnderscoreIvar]);
// --> 3 (null)
NSLog([NSString stringWithFormat:@"%i %@", 4, self.simpleProperty]);
// --> 4 Simple property value
NSLog([NSString stringWithFormat:@"%i %@", 5, self.propertyWithUnderscoreIvar]);
// --> 5 Property with underscore value
}
Why are the first three outputs null? Is my own implementation for the properties incorrect?
In your viewDidLoad method you are logging the values of your instance variables (ivars), not your properties. From your code sample above:
This declares two variables in your class – simpleProperty and propertyWithUnderscoreIvar. The following code, on the other hand, declares the properties:
These are declarations only. Objective C is somewhat similar to C#, in that it provides you with easy ways to generate getter’s and setters for your class properties. In Objective-C this is done via the
@synthesizekeyword (which is roughly analogous to C# automatic properties).Those @synthesize keywords in your implementation file create getter and setter methods for you, for your properties. Your first synthesize looks good, it will create a getter and setter for ‘simpleProperty’, backed by the instance variable of the same name. Your second @synthesize is hokey though. It will create a getter and setter for ‘propertyWithUnderscoreIvar’, backed by the instance variable ‘_propertyWithUnderscoreIvar’, which you never declared. This code will work on modern runtimes but not legacy ones (note that even on modern runtimes, your ‘propertyWithUnderscoreIvar’ ivar will be ignored by the @synthesize).
Now as to why your code is printing nulls, in your logging code you do this:
This is accessing the instance variable directly. But you haven’t set the instance variable to any value at this point. What you really meant to do is access the property, like so:
Using
[self simpleProperty]instead will invoke the methodsimplePropertyand return your hard coded value, which is what you’re trying to do.