iPhone Development 101

iPhone 101

Code Tips






Learn iPhone Programming:
Creating Property Variables

This tutorial was written for Xcode 3.2; it's outdated now. For a more up-to-date tutorial, check out Apple's App Development Tutorial to learn how to write iOS apps. There are also lots of other excellent books and online tutorials you can learn from.

If you'd like to find out when the updated version of this class is ready, follow me on twitter:

Now you have two views and two view controllers. How do you make the flower view appear when the user presses the "Show Image" button?

Once again this involves allocating an instance of the view controller and adding it as a subview. This code goes in the showImage method of MyViewController - the method that's called when the user presses the "Show Image" button:

-(IBAction)showImage:(id)sender {
    FlowerViewController *controller = [[FlowerViewController alloc] initWithNibName:@"FlowerView" bundle:nil];
    [self.view addSubview:[controller view]];

There's a problem here though: you've allocated the controller object, but you're never releasingit. If the user opens and closes the flower view window several times, then you end up with a bunch of FlowerViewController instances. This eats up memory and can eventually crash your app. One solution is to use a @property.

Declaring @properties

A @property is a code shortcut. By declaring a variable as a property, you'll be able to use dot-notation and these accessor methods:

// Getters:
[self myController];    // a method that returns the myController instance
self.myController;      // dot-notation: returns the myController instance

// Setter:
// the setPropertyName method assigns a value to the property:
[self setMyController:newController];   

A @property is declared in the header (.h) file, after the closing brackets of the @interface section:

@property type name;
@property (attributes) type name;

A property may have optional attributes:

Readwrite Attributes
readwrite(default)You can read and write to the property.
readonlyThe property is read-only. You can't use the setPropertyName method.
Setter Attributes
assign(default)setPropertyName uses a straight assignment (prop = newvalue). Use this for basic data types like floats, ints, structs, etc.
retainsetPropertyName will release the previously set object and retain the new one. You should use this for all of your Objective-C object types (e.g., descendants of NSObject) except for NSStrings (see below).
copysetPropertyName will release the previously set object and save a copy of the new one. Use this for NSString objects.
Atomicity Attributes
nonatomicFaster than atomic (the default), but not as safe. If you're using threads, stick with atomic.

Consult the docco or here for more gory details.

Read the Apple Objective-C documentation for more info about properties.

Adding @properties to the Header (.h) File:

Edit MyViewController.h and declare a new instance of FlowerViewController:

#import <UIKit/UIKit.h>

@class FlowerViewController;    // This lets the compiler know that
                                // 'FlowerViewController' is a valid class 
                                // and will be imported later (in the.m file).

@interface MyViewController : UIViewController {
    IBOutlet UILabel *nameLabel;
    IBOutlet UIButton *imgButton;
    IBOutlet UITextView *infoText;    
    FlowerViewController *flowerImageView;   // the new instance variable

@property (nonatomic, retain) FlowerViewController *flowerImageView; // declared as a property

- (IBAction)showImage:(id)sender;


The @property declarations go after the closing bracket of the @interface section. Also, you can only create @properties for instance variables that you've already declared in the @interface section. I usually copy the declaration line and paste it into the property section, then add @property (nonatomic, retain) to the front of it.

Adding @properties to the Implementation (.m) File:

After you create the @property declarations in the .h file, you have to add a few things to the .m file to complete the @property setup.

First you must @synthesize any @property variables. @synthesize goes right after the @implementation line:

@implementation MyViewController

@synthesize flowerImageView;

You can synthesize all of your property variables in one line (e.g. @synthesize var1, var2, var3;).

Finally, you must release any retained properties in the dealloc method:

- (void)dealloc {
    [flowerImageView release];
    [super dealloc];

This ensures that any retained instances of that variable are freed when the object is destroyed. This prevents memory leaks.

Also, if you used @class FlowerViewController in the .h file, then you must #import the FlowerViewController's header file at the top of MyViewController.m:

#import "MyViewController.h"
#import "FlowerViewController.h" // add this to import the class header

Assigning A Value To The @property Variable

Now that your property variable is set up, you can go back and edit the showImage method to assign a value to it:

-(IBAction)showImage:(id)sender {
    FlowerViewController *controller = [[FlowerViewController alloc] initWithNibName:@"FlowerView" bundle:nil];
    [self setFlowerImageView:controller];   // assign controller to flowerImageview
    [controller release];                   // and release the controller instance
    [self.view addSubview:[flowerImageView view]];

Here we've allocated a new instance of the FlowerViewController class, and assigned it to the flowerImageView property variable. The flowerImageView variable retains the object (because we used retain as one of the property attributes). Then we release the controller instance to prevent memory leaks. Finally we add the controller's view as a subview.

MyViewController.h MyViewController.m

Additional References