Chapter 12: Key-Value Coding (KVC)

Matthew Campbell, December 18, 2011

Another advanced technique is key value coding or KVC. This involves using a set of NSObject methods that can set or get property values based on their string representation. So, if a class has a name property you can get or set that value by using the dot notation in code or you can query the object with the string name to get or set the value.

This is an alternative to the typical way of working with properties that you can use in situations where you may not know the name of the property you will need at the time of writing the code. You may also use KVC to query arrays of objects or even arrays that are properties of an object.

How to Use KVC

Let’s assume that I have an object of myClass available to me. If I wanted to find the name I could just use dot notation as we have been discussing:

NSLog(@"name: %@", object.name);

Alternatively I could use KVC:

NSLog(@"name: %@", [object valueForKey:@"name"]);

The less than obvious benefit to KVC is that you do not really need to know the name of the property beforehand to use the property value. Again, if you do not see why this is a big deal then this is just solving a problem that you have not yet run into. When you do remember to come back to this section and apply what you learn.

You can also set properties using KVC:

[object setValue:@"New Object Name" forKey:@"name"];

You can even use KVC on hierarchies of objects. So, if I wanted to get the uppercase representation of my string name I could use the valueForKeypath message to do this:

NSLog([object valueForKeyPath:@"name.uppercaseString"]);

The code above hints a bit more at why this technique is powerful. KVC really shines when we have an array of objects that we want to query.

How to Query an Array of Objects

We will end with this very powerful trick. Imagine that you have a list of objects and each object is composed of many properties. There may be some times where you would like to know what property value is in each object in your list. For instance, if you had a list of contacts you may want to just extract every email address that is in the list.

You can do this with KVC very easily. All you need to do is send the valueForKey message to the array that is holding your objects and you will get a new array filled with each value that you asked for. In the example below I will first add three myClass objects to an array:

myClass *object = [[myClass alloc] init];
NSMutableArray *listOfObjects = [[NSMutableArray alloc] init];
object = [[myClass alloc] initWithName:@"FirstName"];
[listOfObjects addObject:object];
object = [[myClass alloc] initWithName:@"AnotherName"];
[listOfObjects addObject:object];
object = [[myClass alloc] initWithName:@"LastName"];
[listOfObjects addObject:object];

Now, to retrieve the value of each name property I will use the valueForKey message to populate a new array with the name values:

NSArray *results = [listOfObjects valueForKey:@"name"];
for(NSString *s in results)
      NSLog(@"name: %@", s);

The code above puts all the name values into the results array and prints them out to the log:

ObjCExamples[4646:20b] name: FirstName
ObjCExamples[4646:20b] name: AnotherName
ObjCExamples[4646:20b] name: LastName

Hands-On Time

Use the class definitions you created in the previous lesson to experiment with key-value coding. Put your objects into an array and find different ways to retrieve property values in your objects. Think of a way to incorporate the idea of protocols into your car and driver system. Implement your idea.