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

Henry Ngan
Henry Ngan
3,592 Points

About property, literals, instance and local variables

Hello everyone, I have been watching the videos about the crystal ball app and I still have many many many many many questions about Objective-C.

The following is the implementation file of the crystal ball app:

- (NSArray *) predictions {          // Why does it not use _underscore here?
    if (_predictions == nil) {          // Why does it use _underscore here?
        _predictions = [[NSArray alloc] initWithObjects:
                                 @"It is certain",
                                 @"All sighs say YES", nil];
    }
    return _predictions;
}

1. What is the underscore prefix in front of predictions? Why do we have to add _ before predictions? What does that do and mean? Is it related to property?

2. Why do I have to use [[NSArray alloc] initWithObjects: @""] ? I tried to use NSArray literal here and I gave me errors.

3. I always hear Amit saying instance variables and local variables, what are they actually? Qhat are the differences?

4. Sometimes we have to use * and sometimes we don't, like

NSArray *someWords;
int someNumbers;

At what time do we need to use it?

5. Sometimes we use

-(void) but sometimes we use -(NSArray *)

What are the differences? Don't they both return something? And what is the use of * in -(NSArray *)? Is it a pointer? If so, what does it point to?

The above are my questions, really thank you for taking time to answer them! It would help me tremendously!

1 Answer

Stone Preston
Stone Preston
42,016 Points

1) When using properties, a setter, a getter, and an ivar (instance variable) are created behind the scenes. When you declare a property

@property (nonatomic, strong) NSArray *someArray

a getter method called someArray, a setter method called setSomeArray and an ivar called _someArray are all created behind the scenes for you when its compiled. You can use [self someArray] or self.someArray to use the getter method of someArray to access that ivar, the setter method [self setSomeArray] or self.someArray to use the setter method to set that ivar, or you can use _someArray to access that ivar directly. If you are overriding the setter and getter methods for a property, you need to access the ivar directly inside that method

- (NSArray *) predictions { //you dont use the underscore here because the getter method just uses the propert name as its name
    if (_predictions == nil) {     //you use the underscore here because oyu need to access the ivar directly inside the getter method
        _predictions = [[NSArray alloc] initWithObjects:
                                 @"It is certain",
                                 @"All sighs say YES", nil];
    }
    return _predictions;
}

2) an NSArray literal should have worked fine (I think). I would think this would work

- (NSArray *) predictions { //you dont use the underscore here because the getter method just uses the propert name as its name
    if (_predictions == nil) {     //you use the underscore here because oyu need to access the ivar directly inside the getter method
        _predictions = @[@"It is certain", @"some other stuff", @"some other stuff"];
    }
    return _predictions;
}

3) instance variables have instance scope, meaning that they can be used throughout the entire class and are specific to the object. So you could have 2 objects of the same class, but they both have there own separate instance variables. They are also called member variables in other languages. Local variables are scoped to the function, method, or control flow block they are declared in. So if you declare a variable inside a method, then that is a local variable and you can only access it within the method itself, not outside of it. If you wanted to to be able to access it anywhere in your class, you would need to add it as an instance variable or property.

4) you use * when declaring and dereferencing pointers. All objects in objective C are declared as pointers. However you dont have to dereference objects usually. So if I wanted to declare an NSArray object I would need to declare it as a pointer using *

NSArray *someArray;

and I could reference that object just by using its name

someArray[0] = @"hello";

ints and other primitive types dont have to be declared as pointers (though you can do that if you wanted to). so thats why you see

int someInt;

used. Its just a plain primitive type variable.

5) a method declaration generally looks like this

- (returnType)methodName:(dataType)parameter;

when you have a return type of void, that means nothing is returned so

- (void)doSomething;

means thats a method that does not return anything. On the other hand if you had NSArray * as the return type

- (NSArray *)doSomething;

that means that method returns a pointer to an NSArray.

Henry Ngan
Henry Ngan
3,592 Points

Thanks so much!! I now can understand most of it. Really a big thumb for taking so much time to type all this!

Stone Preston
Stone Preston
42,016 Points

no problem. These topics are probably the main things people get confused about. Especially the property accessor methods/when to use self.propertyName and when to use _propertyName, and pointers.