Sandro
Sandro

Reputation: 3160

Problems understanding the concept of access on properties

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

Answers (3)

Perception
Perception

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

dasdom
dasdom

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

EmptyStack
EmptyStack

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

Related Questions