< Previous PageNext Page > Hide TOC

Basic Accessor Methods

There are two basic forms of accessor, a "get accessor", and a "set accessor". You use the get accessor to retrieve a property value from an object; you use the set accessor to set a property value in an object. You can use the Objective-C 2.0 Properties feature to declare and implement accessor methods.

The implementation of an accessor method depends on the type of the property to which it provides access—that is, whether the property is an attribute or a relationship, and if it is a relationship whether it is a to-one or a to-many relationship—see Cocoa Design Patterns for more details. It also depends on whether you are using garbage collection.

Important: The accessor methods shown here are not thread-safe in a managed memory environment, where thread-safety requires the use of a lock which incurs considerable overhead. Typically you cannot express thread-safety at the level of an individual accessor method (see Threading Programming Guide).

Contents:

Objective-C Properties
Attributes
Relationships


Objective-C Properties

You can use the Objective-C 2.0 properties feature to avoid the need to write accessor methods yourself. In your class interface, you declare a specification for the properties using @property:

@interface MyClass : NSObject
{
    NSString *myString;
    BOOL valid;
}
@property (copy, nonatomic) NSString *myString;
@property (nonatomic, getter=isValid) valid;
@end

In the implementation, you use @synthesize to direct the compiler to generate accessor methods corresponding to the property specification:

@implementation MyClass
@synthesize myString;
@synthesize valid;
@end

For full details, see Properties.

In most cases, this should be all you need. Sometimes, however, you may need to implement your own accessor methods—for example, for relationships you may want to make a mutable copy of a new value in a setter method. Even if you do implement custom accessors, you are encouraged to declare properties since they make your intent explicit.

Attributes

Attributes are defining characteristics of a model object.

Object Attributes

For performance reasons, the get accessor typically simply returns the value.

- (NSString *)firstName
{
    return firstName;
}

In the set accessor, you should typically make a copy of the new value that is then private to the model object, as shown in this example:

- (void)setFirstName:(NSString *)aFirstName
{
    if (firstName != aFirstName)
    {
        [firstName release]; // omit if you only support a garbage-collected environment
        firstName = [aFirstName copy];
    }
}

Note that this requires the attribute to implement the NSCopying protocol. Most of the basic Cocoa classes you might use as an attribute implement NSCopying. If you implement a custom class to represent an attribute, it is typically easy to also implement the copy method. In cases where a class is immutable, this might simply retain self.

Non-Object Attribute Types

The following examples illustrate accessor methods for non-object attribute types.

- (NSRect)bounds
{
    return bounds;
}
 
- (void)setBounds:(NSRect)newBounds
{
    bounds = newBounds;
}

You typically also choose a suitable means of representing a nil value using the given attribute type. To properly integrate with key-value coding (see “Key-Value Technology Compliance”) you should implement setNilValueForKey: as illustrated in the following example.

- (void)setNilValueForKey:(NSString *)key
{
    if ([key isEqualToString:@"bounds"]
    {
        bounds = NSMakeRect(0,0,0,0);
    }
    else
    {
        [super setNilValueForKey:key];
    }
}

Relationships

The semantics of accessor methods for a relationship depend on whether the relationship is a to-one or a to-many relationship. In a to-one relationship, you maintain a reference to a related object; in a to-many relationship you need a private collection that maintains references to related objects. In addition, there are special accessors for to-many relationships that may make access more efficient and that allow you to represent the relationship using something other than a collection object.

To-One Relationship

In contrast to an attribute, a relationship is not a private characteristic of an object. As with the attribute, the get accessor typically simply returns the value.

- (Department *)department
{
    return department;
}

The set accessor does not copy a new value. If you use a managed memory environment, or if you need to support both managed memory and garbage collection, you release the old value and retain the new (retain and release are no-ops in a garbage-collected environment):

- (void)setDepartment:(Department *)newDepartment
{
    if (newDepartment != department)
    {
        [department release];
        department = [newDepartment retain];
    }
}

If you use garbage collection, you can simply assign the new value:

- (void)setDepartment:(Department *)newDepartment
{
    department = newDepartment;
}

To-Many Relationship

There are two forms of accessor for to-many relationships—the simple get and set form that follows the same pattern as attributes and to-one relationships, and the collection form. The latter is primarily used for integration with key-value coding and key-value observing.

- (NSArray *)employees
{
    return employees;
}
- (void)setEmployees:(NSMutableArray *)newEmployees
{
    if (employees != newEmployees)
    {
        [employees autorelease];
        employees = [newEmployees mutableCopy];
    }
}

Collection Accessors

Collection accessors follow patterns, different for sets and arrays. The patterns are described in Key-Value Coding Programming Guide, but here is a summary. Given a relationship named <key> :

The following example illustrates collection accessors for an array; the analogous methods for sets are illustrated in Managed Object Accessor Methods.

- (NSUInteger)countOfEmployees
{
    return [employees count];
}
 
- (id)objectInEmployeesAtIndex:(NSUInteger)idx
{
    return [employees objectAtIndex:idx];
}
 
- (void)insertObject:(id)anObject inEmployeesAtIndex:(NSUInteger)idx
{
    [employees insertObject:anObject atIndex:idx];
}
 
- (void)removeObjectFromEmployeesAtIndex:(NSUInteger)idx
{
    [employees removeObjectAtIndex:index];
}
 
- (void)replaceObjectInEmployeesAtIndex:(NSUInteger)idx withObject:(id)anObject
{
    [employees replaceObjectAtIndex:idx withObject:anObject];
}



< Previous PageNext Page > Hide TOC


© 2008 Apple Inc. All Rights Reserved. (Last updated: 2008-02-08)


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.