Mac OS X Reference Library Apple Developer
Search

Accessor Methods

This article describes why you should use accessor methods, and how you should declare and implement them.

One of the principal reasons for using accessor methods is encapsulation (see “Encapsulation” in Object-Oriented Programming with Objective-C). In a reference counted environment, a particular benefit is that they can take care of most of the basic memory management for your classes.

Declaring Accessor Methods

You should typically use the Objective-C declared properties feature to declare accessor methods, for example:

@property (copy) NSString *firstName;
@property (readonly) NSString *fullName;
@property (retain) NSDate *birthday;
@property NSInteger luckyNumber;

The declaration makes explicit the memory management semantics for the property.

Implementing Accessor Methods

In many cases you can (and should) avoid implementing your own accessor methods by using the Objective-C declared properties feature and asking the compiler to synthesize accessor methods for you:

@synthesize firstName;
@synthesize fullName;
@synthesize birthday;
@synthesize luckyNumber;

Even if you need to provide your own implementation, you should declare accessors using a declared property—you must ensure, of course, that your implementation meets the specification you give. (Note in particular that by default a declared property is atomic; if you don’t provide an atomic implementation, you should specify nonatomic in the declaration.)

For simple object values, there are, broadly speaking, three ways to implement the accessors:

  1. Getter retains and autoreleases the value before returning it; setter releases the old value and retains (or copies) the new value.

  2. Getter returns the value; setter autoreleases the old value and retains (or copies) the new value.

  3. Getter returns the value; setter releases the old value and retains (or copies) the new value.

Technique 1

In technique 1, values returned by the getter are autoreleased within the calling scope:

- (NSString*) title {
    return [[title retain] autorelease];
}
 
- (void) setTitle: (NSString*) newTitle {
    if (title != newTitle) {
        [title release];
        title = [newTitle retain]; // Or copy, depending on your needs.
    }
}

Because the object returned from the get accessor is autoreleased in the current scope, it remains valid if the property value is changed. This makes the accessor more robust, but at the cost of additional overhead. If you expect your getter method to be called frequently, the added cost of retaining and autoreleasing the object may not be worth the performance cost.

Technique 2

Like technique 1, technique 2 also uses an autorelease technique, but this time does so in the setter method:

- (NSString*) title {
    return title;
}
 
- (void) setTitle: (NSString*) newTitle {
    [title autorelease];
    title = [newTitle retain]; // Or copy, depending on your needs.
}

The performance of technique 2 is significantly better than technique 1 in situations where the getter is called much more often than the setter.

Technique 3

Technique 3 avoids the use of autorelease altogether:

- (NSString*) title {
    return title;
}
 
- (void) setTitle: (NSString*) newTitle {
    if (newTitle != title) {
        [title release];
        title = [newTitle retain]; // Or copy, depending on your needs.
    }
}

The approach used by technique 3 is good for frequently called getter and setter methods. It is also good for objects that do not want to extend the lifetime of their values, such as collection classes. Its disadvantage is that the old value may be deallocated immediately (if there are no other owners), which will cause a problem if another object is maintaining a non-owning reference to it. For example:

NSString *oldTitle = [anObject title];
[anObject setTitle:@"New Title"];
NSLog(@"Old title was: %@", oldTitle);

If anObject was the only object that owned the original title string, then the string will be deallocated after the new title is set. The log statement would then cause a crash as oldTitle is a freed object.

Value Objects and Copying

It is common practice in Objective-C code to copy value objects—objects that represent attributes. C-type variables can usually be substituted for value objects, but value objects have the advantage of encapsulating convenient utilities for common manipulations. For example, NSString objects are used instead of character pointers because they encapsulate encoding and storage.

When value objects are passed as method arguments or returned from a method, it is common to use a copy instead of the object itself. For example, consider the following method for assigning a string to an object’s name instance variable.

- (void)setName:(NSString *)aName {
    [name autorelease];
    name = [aName copy];
}

Storing a copy of aName has the effect of producing an object that is independent of the original, but has the same contents. Subsequent changes to the copy don’t affect the original, and changes to the original don’t affect the copy. Similarly, it is common to return a copy of an instance variable instead of the instance variable itself. For example, this method returns a copy of the name instance variable:

- (NSString *)name {
    return [[name copy] autorelease];
}



Last updated: 2010-06-24

Did this document help you? Yes It's good, but... Not helpful...