Reputation: 3160
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?
Upvotes: 0
Views: 99
Reputation: 80603
In your viewDidLoad method you are logging the values of your instance variables (ivars), not your properties. From your code sample above:
@interface RootViewController : UITableViewController {
NSString *simpleProperty;
NSString *propertyWithUnderscoreIvar;
}
This declares two variables in your class - simpleProperty and propertyWithUnderscoreIvar. The following code, on the other hand, declares the properties:
@property (nonatomic, retain) NSString *simpleProperty;
@property (nonatomic, retain) NSString *propertyWithUnderscoreIvar;
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 @synthesize
keyword (which is roughly analogous to C# automatic properties).
@synthesize simpleProperty;
@synthesize propertyWithUnderscoreIvar = _propertyWithUnderscoreIvar;
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:
NSLog([NSString stringWithFormat:@"%i %@", 1, simpleProperty]);
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:
NSLog([NSString stringWithFormat:@"%i %@", 1, [self simpleProperty]);
Using [self simpleProperty]
instead will invoke the method simpleProperty
and return your hard coded value, which is what you're trying to do.
Upvotes: 1
Reputation: 14063
These
- (NSString *)simpleProperty {
return @"Simple property value";
}
- (NSString *)propertyWithUnderscoreIvar {
return @"Property with underscore value";
}
are accessors. In
NSLog([NSString stringWithFormat:@"%i %@", 1, simpleProperty]);
you are accessing the ivar directly. Therefore these ivars are null as you haven't set anything to them. In
NSLog([NSString stringWithFormat:@"%i %@", 4, self.simpleProperty]);
you are accessing the ivar via the accessor. Therefore the runtime calls your accessor. In my opinion, when you use @synthesize
you shouldn't write your own accessors. At least when you just started to write in Objective C. In addition your accessor is kind of strange.
Upvotes: 0
Reputation: 51374
In order to access the getter/setter methods you should use self
or any instance
.
NSLog([NSString stringWithFormat:@"%i %@", 1, self.simpleProperty]);
The above line will print @"Simple property value"
as you expect.
Upvotes: 0