Key-value coding attempts to use accessor methods to get and set values, before resorting to directly accessing the instance variable. This article describes how the key-value coding methods determine how the value is accessed.
Accessor Search Patterns for Simple Attributes
Accessor Search Pattern for Ordered Collections
Accessor Search Pattern for Unordered Collections
Mac OS X Version 10.3 Compatibility Notes
When the default implementation of setValue:forKey:
is invoked for a property the following search pattern is used:
The receiver’s class is searched for an accessor method whose name matches the pattern -set<Key>:
.
If no accessor is found, and the receiver’s class method accessInstanceVariablesDirectly
returns YES
, the receiver is searched for an instance variable whose name matches the pattern _<key>
, _is<Key>
, <key>
, or is<Key>
, in that order.
If a matching accessor or instance variable is located, it is used to set the value. If necessary, the value is extracted from the object as described in “Representing Data as Objects.”
If no appropriate accessor or instance variable is found, setValue:forUndefinedKey:
is invoked for the receiver.
When the default implementation of valueForKey:
is invoked on a receiver, the following search pattern is used:
Searches the class of the receiver for an accessor method whose name matches the pattern -get<Key>
, -<key>
, or -is<Key>
, in that order. If such a method is found it is invoked. If the type of the method's result is an object pointer type the result is simply returned. If the type of the result is one of the scalar types supported by NSNumber
conversion is done and an NSNumber
is returned. Otherwise, conversion is done and an NSValue
is returned. In Mac OS 10.5 and later results of arbitrary types are converted to NSValue
objects, not just NSPoint
, NSRange
, NSRect
, and NSSize
types).
Otherwise (no simple accessor method is found), searches the class of the receiver for methods whose names match the patterns -countOf<Key>
and -objectIn<Key>AtIndex:
(corresponding to the primitive methods defined by the NSArray
class) and -<key>AtIndexes:
(corresponding to the NSArray
method objectsAtIndexes:
).
If the countOf<Key>
method and at least one of the other two possible methods are found, a collection proxy object that responds to all NSArray methods is returned. Each NSArray
message sent to the collection proxy object will result in some combination of -countOf<Key>
, -objectIn<Key>AtIndex:
, and -<key>AtIndexes:
messages being sent to the original receiver of valueForKey:
. If the class of the receiver also implements an optional method whose name matches the pattern -get<Key>:range:
that method will be used when appropriate for best performance.
Otherwise (no simple accessor method or set of array access methods is found), searches the class of the receiver for a threesome of methods whose names match the patterns -countOf<Key>
, -enumeratorOf<Key>
, and -memberOf<Key>:
(corresponding to the primitive methods defined by theNSSet
class).
If all three methods are found a collection proxy object that responds to all NSSet
methods is returned. Each NSSet
message sent to the collection proxy object will result in some combination of -countOf<Key>
, -enumeratorOf<Key>
, and -memberOf<Key>:
messages being sent to the original receiver of valueForKey:
.
Otherwise (no simple accessor method or set of collection access methods is found), if the receiver's class' accessInstanceVariablesDirectly
method returns YES
, the class of the receiver is searched for an instance variable whose name matches the pattern _<key>
, _is<Key>
, <key>
, or is<Key>
, in that order. If such an instance variable is found, the value of the instance variable in the receiver is returned. If the type of the result is one of the scalar types supported by NSNumber
conversion is done and an NSNumber
is returned. Otherwise, conversion is done and an NSValue
is returned. In Mac OS 10.5 and later, results of arbitrary types are converted to NSValue
objects, not just NSPoint
, NSRange
, NSRect
, and NSSize
types.
If none of the above situations return a result the default implementation invokes valueForUndefinedKey:
.
The default search pattern for mutableArrayValueForKey:
is as follows:
The receiver's class is searched for a pair of methods whose names match the patterns -insertObject:in<Key>AtIndex:
and -removeObjectFrom<Key>AtIndex:
(corresponding to the NSMutableArray
primitive methods insertObject:atIndex:
and removeObjectAtIndex:
respectively), or methods matching the pattern -insert<Key>:atIndexes:
and -remove<Key>AtIndexes:
(corresponding to the NSMutableArray
insertObjects:atIndexes:
and removeObjectsAtIndexes:
methods).
If at least one insertion method and at least one removal method are found each NSMutableArray
message sent to the collection proxy object will result in some combination of -insertObject:in<Key>AtIndex:
, -removeObjectFrom<Key>AtIndex:
, -insert<Key>:atIndexes:
, and -remove<Key>AtIndexes:
messages being sent to the original receiver of mutableArrayValueForKey:
.
If receiver's class also implements the optional replace object method matching the pattern -replaceObjectIn<Key>AtIndex:withObject:
or -replace<Key>AtIndexes:with<Key>:
that method will be used when appropriate for best performance.
Otherwise the receiver's class is searched for an accessor method whose name matches the pattern -set<Key>:
. If such a method is found each NSMutableArray
message sent to the collection proxy object will result in a -set<Key>:
message being sent to the original receiver of mutableArrayValueForKey:
. It is much more efficient to implement the indexed accessor methods discussed in the previous step.
Otherwise if the receiver's class responds YES
to accessInstanceVariablesDirectly
, the receiver's class is searched for an instance variable whose name matches the pattern _<key>
or <key>
, in that order.
If such an instance variable is found, each NSMutableArray
message sent to the collection proxy object will be forwarded to the instance variable's value, which typically will be an instance of NSMutableArray
or a subclass of NSMutableArray
.
Otherwise returns a mutable collection proxy object that results in a setValue:forUndefinedKey:
message being sent to the original receiver of the mutableArrayValueForKey:
message whenever the proxy receives an NSMutableArray
message.
The default implementation of setValue:forUndefinedKey: raises an NSUndefinedKeyException
, but you can override it in your application.
Note: The repetitive set<Key>:
messages implied by Step 2's description are a potential performance problem. For better performance implement methods that fulfill the requirements for Step 1 in your key-value coding-compliant class.
The default search pattern for mutableSetValueForKey:
is as follows:
Searches the receiver's class for methods whose names match the patterns -add<Key>Object:
and -remove<Key>Object:
(corresponding to the NSMutableSet
primitive methods addObject:
and removeObject:
respectively) and also -add<Key>:
and -remove<Key>:
(corresponding to NSMutableSet
methods unionSet:
and minusSet:
). If at least one addition method and at least one removal method are found each NSMutableSet
message sent to the collection proxy object will result in some combination of -add<Key>Object:
, -remove<Key>Object:
, -add<Key>:
, and -remove<Key>:
messages being sent to the original receiver of mutableSetValueForKey:
.
If the class of the receiver also implements an optional method whose name matches the pattern -intersect<Key>:
or -set<Key>:
that method will be used when appropriate for best performance.
If the receiver is a managed object the search pattern does not continue as it would for non-managed objects. See Managed Object Accessor Methods in Model Object Implementation Guide for more information.
Otherwise, the receiver's class is searched for an accessor method whose name matches the pattern -set<Key>:
. If such a method is found each NSMutableSet message sent to the collection proxy object will result in a -set<Key>:
message being sent to the original receiver of mutableSetValueForKey:
.
Otherwise, if the receiver's class method accessInstanceVariablesDirectly
returns YES
, the class is searched for an instance variable whose name matches the pattern _<key>
or <key>
, in that order. If such an instance variable is found, each NSMutableSet
message sent to the collection proxy object will be forwarded to the instance variable's value, which therefore must typically be an instance of NSMutableSet
or a subclass of NSMutableSet
.
Otherwise, returns a mutable collection proxy object anyway. Each NSMutableSet
message sent to the collection proxy object will result in a setValue:forUndefinedKey:
message being sent to the original receiver of mutableSetValueForKey:
.
Note: The repetitive set<Key>:
messages implied by Step 3's description are a potential performance problem. For better performance implement methods that fulfill the requirements for Step 1 in your key-value coding-compliant class.
Mac OS X v10.3 deprecated a number of existing key-value coding methods, replacing them with methods that provide similar functionality.
Deprecated method |
Replacement method |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The following compatibility notes are relevant to the accessor search patterns discussed in “Default Search Pattern for setValue:forKey:” and “Default Search Pattern for valueForKey:”:
For backward binary compatibility with the behavior of takeValue:forKey:
, a method whose name matches the pattern -_set<Key>:
is also recognized in step 1. KVC accessor methods whose names start with underscores are deprecated as of Mac OS X v10.3.
For backward binary compatibility, unableToSetNilForKey:
is invoked instead of setNilValueForKey:
in step 1 if the receiver’s implementation of unableToSetNilForKey:
is not NSObject’s implementation.
The behavior described in step 2 is different from that of takeValue:forKey:
, in which the instance variable search order is <key>
, _<key>
.
For backward binary compatibility with the behavior of takeValue:forKey:
, handleTakeValue:forUnboundKey:
is invoked instead of setValue:forUndefinedKey:
in step 4 if the receiver’s implementation of handleTakeValue:forUnboundKey:
is not NSObject's implementation.
© 2003, 2009 Apple Inc. All Rights Reserved. (Last updated: 2009-02-04)