iOS

Objective – C Properties

An object’s properties let other objects inspect or change its state. But, in a well-designed object-oriented program, it’s not possible to directly access the internal state of an object. Instead, accessor methods(getters and setters) are used as an abstraction for interacting with the object’s underlying data.

The goal of the @property directive is to make it easy to create and configure properties by automatically generating these accessor methods. It allows you to specify the behavior of a public property on a semantic level, and it takes care of the implementation details for you.

This module surveys the various attributes that let you alter getter and setter behavior. Some of these attributes determine how properties handle their underlying memory, so this module also serves as a practical introduction to memory management in Objective-C.

The @property Directive

First, let’s take a look at what’s going on under the hood when we use the @property directive. Consider the following interface for a simple Car class and its corresponding implementation.

// Car.h
#import <Foundation/Foundation.h>

@interface Car : NSObject

@property BOOL running;

@end


// Car.m
#import "Car.h"

@implementation Car

@synthesize running = _running;    // Optional for Xcode 4.4+

@end

The compiler generates a getter and a setter for the running property. The default naming convention is to use the property itself as the getter, prefix it with set for the setter, and prefix it with an underscore for the instance variable, like so:

- (BOOL)running {
    return _running;
}
- (void)setRunning:(BOOL)newValue {
    _running = newValue;
}

After declaring the property with the @property directive, you can call these methods as if they were included in your class’s interface and implementation files. You can also override them in Car.m to supply custom getter/setters, but this makes the @synthesize directive mandatory. However, you should rarely need custom accessors, since@property attributes let you do this on an abstract level.

Properties accessed via dot-notation get translated to the above accessor methods behind the scenes, so the following honda.runningcode actually calls setRunning: when you assign a value to it and therunning method when you read a value from it:

 

// main.m
#import <Foundation/Foundation.h>
#import "Car.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Car *honda = [[Car alloc] init];
        honda.running = YES;                // [honda setRunning:YES]
        NSLog(@"%d", honda.running);        // [honda running]
    }
    return 0;
}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s