Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS Build a Simple iPhone App (iOS7) Refactoring into a Model Understanding @property

Defining (customising) a @property's getter method

Hello,

In this lesson:

http://teamtreehouse.com/library/build-a-simple-iphone-app-ios7-2/refactoring-into-a-model/understanding-property

After refactoring into a model for the Crystal Ball app:

#import <Foundation/Foundation.h>

@interface BBthegrandpa : NSObject

@property (strong, nonatomic) NSArray *predictions;

- (NSString*) randomPrediction;

@end
#import "BBthegrandpa.h"

@implementation BBthegrandpa

- (NSArray *) predictions {

    if (_predictions == nil) {
        _predictions = [[NSArray alloc] initWithObjects:
                        @"It is certain",
                        @"It is decidedly so",
                        @"Consult the Oxford dictionary",
                        @"Concentrate and ask again",
                        @"Eh? You'll have to speak louder than that",
                        @"It is doubtful",
                        @"Heavens no!",
                        @"I don't know. Have you gained weight?",
                        @"Yes. I mean no. Wait, what did you ask?", nil];
    }

    return _predictions;
}

- (NSString *) randomPrediction {
    int random = arc4random_uniform(self.predictions.count);
    return [self.predictions objectAtIndex:random];
}

@end

I'm wondering why we explicitly define the getter method and not the setter method as well (or the setter method instead of the getter method).

Cheers

2 Answers

Mike Baxter
Mike Baxter
4,442 Points

If you override the setter method, Xcode will see that you did a manual override of both the getter and the setter functions, so it will not synthesize the _predictions variable. If that were the case, you would manually have to declare the _predictions instance variable like this:

@interface BBthegrandpa : NSObject {
    NSArray *_predictions;
}

@property (strong, nonatomic) NSArray *predictions;

The same goes for if you were to declare the property read-only as well, like this:

@property (strong, nonatomic, readonly) NSArray *predictions;

You would have to manually declare the instance variable in that case as well, since "readonly" would never synthesize a setter method, and therefore you would be overriding all the synthesized methods (in the case of readonly, only the getter method is auto-synthesized).

Hope that helps!

Cheers Mike. What exactly do you mean by 'synthesize'?

Edit: dw it means defining?

Mike Baxter
Mike Baxter
4,442 Points

I mean that when you declare "@property" for anything, Xcode automatically generates the getter and setter methods for you. This is sometimes called "synthesizing," so you could say that Xcode synthesizes the getter and setter methods for you. But you want to return some custom information when asking for this _predictions array, so you "override" it by declaring it yourself. However, you could definitely just declare the method yourself like this:

@interface BBthegrandpa : NSObject {
    NSArray *_predictions;
}

-(NSArray *)predictions;

In the header file, and then implement it in the .m file, but I think the point of the lesson is to teach you the convenience of the property. The catch 22 is what I mentioned in my answerβ€”that in certain cases when you override what a @property does, you might run into the case where Xcode never sets up your _predictions variable for you. So in this specific case, it's useful not to write your own setter method, because doing so would trigger Xcode to not set up (or synthesize) a _predictions variable for you.

Aaaaahhhhh ok

The only thing that confuses me about the addition of readonly and subsequent instance variable declaration is that in the implementation file it's like, you're still customising the getter – but hasn't the getter disappeared? (Been removed by readonly?)

@implementation BBthegrandpa

- (NSArray *) predictions {

    if (_predictions == nil) {
        _predictions = [[NSArray alloc] initWithObjects:
                        @"It is certain",
                        @"It is decidedly so",
                        @"Consult the Oxford dictionary",
                        @"Concentrate and ask again",
                        @"Eh? You'll have to speak louder than that",
                        @"It is doubtful",
                        @"Heavens no!",
                        @"I don't know. Have you gained weight?",
                        @"Yes. I mean no. Wait, what did you ask?", nil];
    }

    return _predictions;
}

- (NSString *) randomPrediction {
    int random = arc4random_uniform(self.predictions.count);
    return [self.predictions objectAtIndex:random];
}

@end
Mike Baxter
Mike Baxter
4,442 Points

bronnyreinhardt , readonly would cause Xcode to synthesize the getter only. A readonly variable means that you can only get it's value, you can't set it. So readonly prevents a setter from being made, but it would still auto-synthesize the getter method. However, since the implementation file is overriding the getter method (which is the one-and-only method a readonly-synthesized array would make), you would need to explicitly declare the NSArray *_predictions instance variable in the header file. Hope that makes sense!

Rashii Henry
Rashii Henry
16,433 Points

creating an @property defines the setters and getters for you. && which method are you talking about specifically?

As I understand it, the predefined getter method created by the property (in the first code block) is being customised (or redefined) in the second code block.

My question was: why do we redefine the getter, and the not the setter? Or not both?