Properties Tutorial for iOS
Learn how to use properties in this properties tutorial, the third in a 3-part series on memory management. By Ray Wenderlich.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Properties Tutorial for iOS
15 mins
A Simple Proposition
So writing getters and setters can be useful to give other classes access to your instance variables, and also sometimes make managing memory easier.
But writing these methods over and over again can be a royal pain! Nobody likes doing the same thing over and over, so Objective-C has a really useful feature to help with this: properties.
We can replace all of the getter/setter code you wrote earlier with just a few lines! Try it out to see for yourself. Go to RootViewController.h, remove the getter and setter prototypes and replace it with this:
@property (nonatomic, retain) NSArray * sushiTypes;
@property (nonatomic, retain) NSString * lastSushiSelected;
This is step one one of using properties: to create the property declarations.
A property declaration starts with the @property keyword. Then in parenthesis you put the property attributes (which we’ll discuss in a second). Finally, you give the type and name of the property.
Property attributes are special keywords to tell compiler how to generate the getters and setters. Here you specify two property attributes: nonatomic, which tells the compiler not to worry about multithreading, and retain, which tells the compiler to retain the passed-in variable before setting the instance variable.
In other situations, you might want to use the “assign” property attribute instead of retain, which tells the compiler NOT to retain the passed-in variable. Or perhaps the “copy” property attribute, which makes a copy of the passed-in variable before setting.
Ok! To finish using the properties, switch over to RootViewController.m, delete the getters and setters you wrote earlier, and add this to the top of the file:
@synthesize sushiTypes = _sushiTypes;
@synthesize lastSushiSelected = _lastSushiSelected;
This line is the line that instructs the compiler to automatically create the getter and setter code based on the property definitions that you added in the header file. You start with the @synthesize keyword, then give the name of the property, then (if it has a different name) tell it the instance variable that should back the property.
And that’s it! Compile and run the code, and it should work just as before. But if you compare your code now to what you started with, I think you’ll agree that it’s a little bit easier to understand, and less error prone.
Plus you just learned about properties and how they work!
Synthesize A Strategy
I’d like to wrap up the article with a little strategy that I sometimes like to use to simplify memory management in Objective-C.
If you follow these rules, you’ll keep yourself out of memory-related trouble most of the time. Of course, blindly following rules is not a substitute for understanding what’s going on, but it can make things simpler and help you avoid mistakes, especially when you are first starting.
I’ll list the rules out first, and then we’ll have a discussion of each one.
- Always make a property for every instance variable.
- If it’s a class, mark it with the retain attribute. Otherwise, mark it with the assign attribute.
- Whenever creating a variable, use the alloc/init/autorelease idiom.
- Whenever setting a variable, always use “self.xxx = yyy” (in other words, use the property).
- For each of your instance variables, call “self.xxx = nil” in dealloc. If it’s an outlet or something you created in viewDidLoad, do the same in viewDidUnload.
Ok, now onto the discussion!
For rule #1: By making an instance variable for each property, you can let the compiler write the memory management code for you. The drawback is it doesn’t keep the private data of your class well encapsulated so can lead to more connected code if you are not careful.
For rule #2: By retaining variables whenever they are set, you can make sure that you can access your instance variables at any time.
For rule #3: When you create a variable, you want to use the alloc/init/autorelease idiom (like you can see creating the NSArray with the sushiTypes earlier). This way, the memory will be freed up for you automatically later on. If you need to keep the variable around long-term, you should assign it to a property, put it in an array, or the like to increment the reference count.
For rule #4: By using the self.xxx syntax (i.e. using the property) whenever you set a variable, you’ll go through the properties and hence make sure to release the old variable/retain the new variable. Note some programmers worry about using getters/setters/properties in initializers and dealloc, but I don’t think it’s something to worry about if you wrote & understand the code.
For rule #5: Calling “self.xxx = nil” will go through your properties and decrement the reference count. Don’t forget about viewDidUnload!
Simplified Strategy for Cocos2D
There’s a lot of rabid Cocos2D fans on this blog, so wanted to add a special section for you guys ;]
The above strategy is usually overkill for Cocos2D, because most of the time your instance variables are just handy references to objects you want to use a lot in your current layer. And Cocos2D will keep a retain count on these objects as long as they are currently in the layer.
So to avoid making unnecessary properties for everything, here’s what I like to use for Cocos2D:
- Don’t use properties at all.
- Set instance variables directly to your created sprites, etc.
- Since they’ll be children of the current layer, Cocos2D will keep the retain count up as long as they’re there.
- When you remove the object from the layer, set the instance variable to nil.
I just personally find it simpler and faster to develop this way.
Note this strategy doesn’t work if you want to keep track of an object not currently in the layer – you’ll have to use an alternative strategy there.
Where To Go From Here?
Here is the updated sample project that we developed in the above properties tutorial, now using properties.
If you have any questions about properties or memory management in general, feel free to leave a question in the forums below! Also please chime in if you have any different memory management strategies, tips, or advice that may be useful to other developers.
That about wraps up this Objective-C tutorial series on memory management. Hopefully it has helped take a bit of the mystery out of memory management in Objective-C!