If there is no accessor or instance variable for the specified key, then the receiver sends itself a
valueForUndefinedKey:
message. The default implementation of
valueForUndefinedKey:
raises an
NSUndefinedKeyException;
subclasses can
override
this behavior.
The default implementations of
dictionaryWithValuesForKeys:
and
setValuesForKeysWithDictionary:
translates between
NSNull
and
nil
automatically, so your objects don’t have to explicitly test for
NSNull
values
----------------------------------------------------------------
setValue:forKey:
If the specified key does not exist, the receiver is sent a
setValue:forUndefinedKey:
message. The default implementation of
setValue:forUndefinedKey:
raises an
NSUndefinedKeyException;
however, subclasses can override this method to handle the request in a custom manner.
The default implementation invokes
setValue:forKey:
for each key-value pair, substituting
nil
for
NSNull
objects as required.
----------------------------------------------------------------
when an attempt is made to set a non-object
- -countOf. Required. This is the analogous to the NSArray primitive method count. -objectInAtIndex: or -AtIndexes:. One of these methods must be implemented. They
- correspond to the NSArray methods objectAtIndex: and objectsAtIndexes:.
- -get:range:. Implementing this method is optional, but offers additional performance gains. This method corresponds to the NSArray method getObjects:range:.
/************************** e.g *********************************************/
- (NSUInteger)countOfEmployees {
return [self.employees count];
}
- (id)objectInEmployeesAtIndex:(NSUInteger)index {
return [employees objectAtIndex:index];
}
- (NSArray *)employeesAtIndexes:(NSIndexSet *)indexes {
return [self.employees objectsAtIndexes:indexes];
}
- (void)getEmployees:(Employee * __unsafe_unretained *)buffer range:(NSRange)inRange {
// Return the objects in the specified range in the provided buffer.
// For example, if the employees were stored in an underlying NSArray
[self.employees getObjects:buffer range:inRange];
}
Mutable Indexed Accessors
mutableArrayValueForKey:
- -insertObject:inAtIndex: or -insert:atIndexes:. At least one of these methods must be implemented. These are analogous to the NSMutableArray methods insertObject:atIndex: and insertObjects:atIndexes:.
- -removeObjectFromAtIndex: or -removeAtIndexes:. At least one of these methods must be implemented. These methods correspond to the NSMutableArray methods removeObjectAtIndex: and removeObjectsAtIndexes: respectively.
- -replaceObjectInAtIndex:withObject: or -replaceAtIndexes:with:. Optional. Implement if benchmarking indicates that performance is an issue.
/************************** e.g *********************************************/
- (void)insertObject:(Employee *)employee inEmployeesAtIndex:(NSUInteger)index {
[self.employees insertObject:employee atIndex:index];
return;
}
- (void)insertEmployees:(NSArray *)employeeArray atIndexes:(NSIndexSet *)indexes
{
[self.employees insertObjects:employeeArray atIndexes:indexes];
return;
}
- (void)removeObjectFromEmployeesAtIndex:(NSUInteger)index {
[self.employees removeObjectAtIndex:index];
}
- (void)removeEmployeesAtIndexes:(NSIndexSet *)indexes {
[self.employees removeObjectsAtIndexes:indexes];
}
- (void)replaceObjectInEmployeesAtIndex:(NSUInteger)index
withObject:(id)anObject {
[self.employees replaceObjectAtIndex:index withObject:anObject];
}
- (void)replaceEmployeesAtIndexes:(NSIndexSet *)indexes
withEmployees:(NSArray *)employeeArray {
[self.employees replaceObjectsAtIndexes:indexes withObjects:employeeArray];
}
Getter Unordered Accessors
- -countOf. Required. This method corresponds to the NSSet method count.
- -enumeratorOf. Required. Corresponds to the NSSet method objectEnumerator.
- -memberOf:. Required. This method is the equivalent of the NSSet method member:
/************************** e.g *********************************************/
- (NSUInteger)countOfTransactions {
return [self.transactions count];
}
- (NSEnumerator *)enumeratorOfTransactions {
return [self.transactions objectEnumerator];
}
- (Transaction *)memberOfTransactions:(Transaction *)anObject {
return [self.transactions member:anObject];
}
Mutable Unordered Accessors
mutableSetValueForKey:
- -addObject: or -add:. At least one of these methods must be implemented. These are analogous to the NSMutableSet method addObject:.
- -removeObject: or -remove:. At least one of these methods must be implemented. These are analogous to the NSMutableSet method removeObject:.
- -intersect:. Optional. Implement if benchmarking indicates that performance is an issue. It performs the equivalent action of the NSSet method intersectSet:.
/************************** e.g *********************************************/
- (void)addTransactionsObject:(Transaction *)anObject {
[self.transactions addObject:anObject];
}
- (void)addTransactions:(NSSet *)manyObjects {
[self.transactions unionSet:manyObjects];
}
- (void)removeTransactionsObject:(Transaction *)anObject {
[self.transactions removeObject:anObject];
}
- (void)removeTransactions:(NSSet *)manyObjects {
[self.transactions minusSet:manyObjects];
}
- (void)intersectTransactions:(NSSet *)otherObjects {
return [self.transactions intersectSet:otherObjects];
}
Validation Method Naming Convention
A validation method has the format
validate:error:
There are three possible outcomes from a validation method:
-
The object value is valid, so YES is returned without altering the value object or the error.
-
The object value is not valid and a valid value cannot be created and returned. In this case NO is returned after setting the error parameter to an NSError object that indicates the reason validation failed.
-
A new object value that is valid is created and returned. In this case YES is returned after setting the value parameter to the newly created, valid value. The error is returned unaltered. You must return a new object, rather than just modifying the passed ioValue, even if it is mutable.
The example in Listing 2 implements a validation method for a
name
property that ensures that the value object is a string and that the name is capitalized correctly.
-(BOOL)validateName:(id *)ioValue error:(NSError * __autoreleasing *)outError{
// The name must not be nil, and must be at least two characters long.
if ((*ioValue == nil) || ([(NSString *)*ioValue length] < 2)) {
if (outError != NULL) {
NSString *errorString = NSLocalizedString(
@"A Person's name must be at least two characters long",
@"validation: Person, too short name error");
NSDictionary *userInfoDict = @{ NSLocalizedDescriptionKey : errorString
};
*outError = [[NSError alloc] initWithDomain:PERSON_ERROR_DOMAIN
code:PERSON_INVALID_NAME_CODE
userInfo:userInfoDict];
return NO;
}
return YES;
}
Invoking Validation Methods
You can call validation methods directly, or by invoking
validateValue:forKey:error:
and specifying the key.
Warning:
An implementation of set: for a property should never call the validation methods.
Automatic Validation
In general, key-value coding does not perform validation automatically—it is your application’s responsibility to invoke the validation methods.
Core Data
automatically performs validation when the managed object context is saved; in OS X, Cocoa bindings allow you to specify that validation should occur automatically
Representing Non-Object Values
The default implementations of
valueForKey:
and
setValue:forKey:
provide support for automatic object wrapping of the non-object data types, both scalars and structs.
即对此两方法的调用自动转换为对应getter和setter方法的Values
Collection Operators
The key path on the left side of the collection operator, if present, determines the array or set, relative to the receiver, that is used in the operation. The key path on the right side of the operator specifies the property of the collection that the operator uses.
Simple Collection Operators
Simple collection operators operate on the properties to the right of the operator in either an array or set
@avg
作用于ritghPath
@count
作用于leftPath the key path to the right of the operator is ignored.
@max
作用于ritghPath If the value of the right side of the key path is nil, it is ignored.
@min
同上
@sum
同上
Object Operators
@distinctUnionOfObjects
作用于ritghPath. This operator raises an exception if any of the leaf objects is nil. returns a array
@unionOfObjects
同上 returns a array
Array and Set Operators
The array and set operators operate on nested collections, that is, a collection where each entry contains a collection
@distinctUnionOfArrays
同distinctUnionOfObjects returns a array
@unionOfArrays
同上 returns a array
@distinctUnionOfSets
同上 returns a set
Accessor Search Patterns for Simple Attributes
Default Search Pattern for
setValue:forKey:
- The receiver’s class is searched for an accessor method whose name matches the pattern set:.
-
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
_, _is, ,
or
is,
in that order.
- If a matching accessor or instance variable is located, it is used to set the value. 注: 跟直接属性调用accessor不同, setValue可能不经过accessor
- If no appropriate accessor or instance variable is found, setValue:forUndefinedKey: is invoked for the receiver.
Default Search Pattern for
valueForKey:
proxy object: NSArray 或 NSSet
- Searches the class of the receiver for an accessor method whose name matches the pattern get, , or is,
- Otherwise, searches countOf and objectInAtIndex: and AtIndexes:……………..If the countOf 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.
- Otherwise, searches the class of the receiver for a threesome of methods whose names match the patterns countOf, enumeratorOf, and memberOf: (corresponding to the primitive methods defined by the NSSet class). ……………..If all three methods are found, a collection proxy object that responds to all NSSet methods is returned.
- Otherwise, if the receiver's class method accessInstanceVariablesDirectly returns YES, the class of the receiver is searched for an instance variable whose name matches the pattern _, _is, , or is,
- If none of the above situations occurs, returns a result the default implementation invokes valueForUndefinedKey:
Accessor Search Pattern for Ordered Collections
The default search pattern for
mutableArrayValueForKey:
is as follows:
proxy object : NSMutableArray
- searches for a pair of methods whose names match the patterns insertObject:inAtIndex: and removeObjectFromAtIndex: , or methods matching the pattern insert:atIndexes: and removeAtIndexes:
- Otherwise, searches set: to response the original receiver of mutableArrayValueForKey:
- 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 _ or
- 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.
Note:
The repetitive
set:
messages implied by the description in step 2 are a potential performance problem. For better performance, implement methods that fulfill the requirements for Step 1 in your key-value coding-compliant class.
Accessor Search Pattern for Uniquing Ordered Collections
mutableOrderedSetValueForKey:
proxy object : NSMutableOrderedSet
- Searches insertObject:inAtIndex: and removeObjectFromAtIndex: and also insert:atIndexes: and removeAtIndexes:………. If at least one insertion method and at least one removal method are found each NSMutableOrderedSet message sent to the collection proxy object will result in some combination of insertObject:inAtIndex:, removeObjectFromAtIndex:, insert:atIndexes:, and removeAtIndexes: messages being sent to the original receiver of mutableOrderedSetValueForKey:.
- Otherwise, searches set:
- 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 _ or
- Otherwise, returns a mutable collection proxy object that results in a setValue:forUndefinedKey:
Accessor Search Pattern for Unordered Collections
mutableSetValueForKey:
proxy object : NSMutableSet
- Searches addObject: and removeObject: and also add: and remove: (corresponding to NSMutableSet methods unionSet: and minusSet:).
-
If the receiver is a managed object, the search pattern does not continue as it would for non-managed objects.
- Otherwise, searches set:
- 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 _ or
- Otherwise, returns a mutable collection proxy object that results in a setValue:forUndefinedKey: