What Is Key-Value Coding?

Key-value coding is a mechanism for accessing an object’s properties indirectly, using strings to identify properties, rather than through invocation of an accessor method or accessing them directly through instance variables. In essence, key-value coding defines the patterns and method signatures that your application’s accessor methods implement.

Accessor methods, as the name suggests, provide access to your application’s data model’s property values. There are two basic forms of accessor—get accessors and set accessors. Get accessors, also referred to as getters, return the values of a property. Set accessors, also referred to as setters, set the value of a property. There are getter and setter variants for dealing with both object attributes and to-many relationships.

Implementing key-value coding compliant accessors in your application is an important design principle. Accessors help to enforce proper data encapsulation and facilitate integration with other technologies such as key-value observing, Core Data, Cocoa bindings, and scriptability. Key-value coding methods can, in many cases, also be utilized to simplify your application’s code.

The essential methods for key-value coding are declared in the NSKeyValueCoding Objective-C informal protocol and default implementations are provided by NSObject.

Key-value coding supports properties with object values, as well as the scalar types and structs. Non-object parameters and return types are detected and automatically wrapped, and unwrapped, as described in “Scalar and Structure Support.”

Key-Value Coding and Scripting

The scripting support in Cocoa is designed so that an application can easily implement scripting by accessing its model objects—the objects that encapsulate the application’s data. When the user executes an AppleScript command that targets your application, the goal is for that command to go directly to the application’s model objects to get the work done.

Scripting in OS X relies heavily on key-value coding to provide automatic support for executing AppleScript commands. In a scriptable application, a model object defines a set of keys that it supports. Each key represents a property of the model object. Some examples of scripting-related keys are words, font, documents, and color. The key-value coding API provides a generic and automatic way to query an object for the values of its keys and to set new values for those keys.

As you design the objects of your application, you should define the set of keys for your model objects and implement the corresponding accessor methods. Then when you define the script suites for your application, you can specify the keys that each scriptable class supports. If you support key-value coding, you will get a great deal of scripting support “for free.”

In AppleScript, object hierarchies define the structure of the model objects in an application. Most AppleScript commands specify one or more objects within your application by drilling down this object hierarchy from parent container to child element. You can define the relationships between properties available through key-value coding in class descriptions. See “Describing Property Relationships” for more details.

Cocoa’s scripting support takes advantage of key-value coding to get and set information in scriptable objects. The method in the Objective-C informal protocol NSScriptKeyValueCoding provides additional capabilities for working with key-value coding, including getting and setting key values by index in multi-value keys and coercing (or converting) a key-value to the appropriate data type.

Using Key-Value Coding to Simplify Your Code

You can use key-value coding methods in your own code to generalize implementations. For example, in OS X NSTableView and NSOutlineView objects both associate an identifier string with each of their columns. By making this identifier the same as the key for the property you wish to display, you can significantly simplify your code.

Listing 1 shows an implementation of an NSTableView delegate method without using key-value coding. Listing 2 shows an implementation that takes advantage of key-value coding to return the appropriate value using the column identifier as the key.

Listing 1  Implementation of data-source method without key-value coding

- (id)tableView:(NSTableView *)tableview
      objectValueForTableColumn:(id)column row:(NSInteger)row {
 
    ChildObject *child = [childrenArray objectAtIndex:row];
    if ([[column identifier] isEqualToString:@"name"]) {
        return [child name];
    }
    if ([[column identifier] isEqualToString:@"age"]) {
        return [child age];
    }
    if ([[column identifier] isEqualToString:@"favoriteColor"]) {
        return [child favoriteColor];
    }
    // And so on.
}

Listing 2  Implementation of data-source method with key-value coding

- (id)tableView:(NSTableView *)tableview
      objectValueForTableColumn:(id)column row:(NSInteger)row {
 
    ChildObject *child = [childrenArray objectAtIndex:row];
    return [child valueForKey:[column identifier]];
}