Database Reference
In-Depth Information
of that object directly. Key Value Coding is implemented through an informal
protocol on
NSObject
itself and is used mainly through the getter/setter pair
-valueForKey:
and
-setValue:forKey:
.
-valueForKey:
The method
-valueForKey:
is a generic accessor that retrieves an attribute on an
object. For example, if we had an object called
Recipe
and it had an attribute
called
name
, normally we would access that attribute via the following:
Recipe *myRecipe = ...
NSString *recipeName = [myRecipe name];
However, this requires specific knowledge about the
Recipe
object to exist in
the calling method and generally requires that we import the header file of
the
Recipe
object. However, with Key Value Coding, we can obtain this same
attribute without any preexisting knowledge about the
Recipe
object.
id myRecipe = ...
NSString *recipeName = [myRecipe valueForKey:@
"name"
];
By itself, this is not all that useful. However, there are huge benefits that are
not obvious on the surface. Here's an example of how you might better take
advantage of this ability:
- (NSString*)description
{
NSMutableString *string = [NSMutableString stringWithFormat:@
"[%@] {"
,
[self class]];
NSEntityDescription *desc = [self entity];
for
(NSString *name in [desc attributeKeys]) {
[string appendFormat:@
"\n\t%@ = '%@'"
, name, [self valueForKey:name]];
}
[string appendString:@
"\n}"
];
return
string;
}
In this example, we utilize the
NSEntityDescription
class (discussed in greater
detail in
Chapter 1,
Under the Hood of Core Data
, on page 1
) to retrieve the
names all of the attributes of an
NSManagedObject
subclass and generate an
NSString
for display in the logs. With this method, we can reuse it in every
NSManagedObject
subclass that we create, rather than having to create a custom
-description
method for each subclass.
There are a couple of things to note in this example. First, the target object
is not required to have accessor methods for the attribute being queried. If
our target object has only an
ivar
or property for a name, it will still be resolved
and retrieved properly. (
ivar
stands for instance variable, which is different