1, what is Key-value Coding? Key-value coding is a mechanism for indirectly accessing object properties, using a string to identify a property, rather than by invoking an access method for an instance variable. The methods used are basically declared from the Nskeyvaluecoding protocol and implemented by NSObject.
Key-value coding supports object properties and also supports scalar and struct types. Non-object parameters and return types are automatically wrapped and wrapped.
The methods defined by Nskeyvaluecoding are:
Ways to get property values:
–valueforkey:
–valueforkeypath:
–dictionarywithvaluesforkeys:
–valueforundefinedkey:
–mutablearrayvalueforkey:
–mutablearrayvalueforkeypath:
–mutablesetvalueforkey:
–mutablesetvalueforkeypath:
–mutableorderedsetvalueforkey:
–mutableorderedsetvalueforkeypath:
To set property values:
–setvalue:forkeypath:
–setvaluesforkeyswithdictionary:
–setnilvalueforkey:
–setvalue:forkey:
–setvalue:forundefinedkey:
Ways to change the default behavior:
+ accessinstancevariablesdirectly
Verification Method:
–validatevalue:forkey:error:
–validatevalue:forkeypath:error:
2, the property value is obtained by KVC: Method Valueforkey: Returns the value of the specified key, and if there is no key, the receiver sends itself a VALUEFORUNDEFINEDKEY: message. The default Valueforundefinedkey: Message causes a nsundefinedkeyexception, and subclasses can overload the behavior.
Valueforkeypath: It's similar.
Method Dictionarywithvaluesforkeys: Retrieves the value of the recipient's set of keys.
Tip: Collection objects, such as nsarray,nsset,nsdictionary, cannot contain nil values, instead, you use specific objects, nsnull.nsnull instead of nil values. The default Dictionarywithvaluesforkeys: and setvaluesforkeyswithdictionary: The implementation of the method automatically converts Nsnull and nil, so your object does not have to test the Nsnull value explicitly.
3, set the property value by KVC: Method Setvalue:forkey:. Its default implementation automatically wraps Nsvalue objects that represent scalar and struct types. If the specified key does not exist, the receiver sends a SETVALUE:FORUNDEFINEDKEY: message. The default implementation of the method throws a Nsundefinedkeyexception exception, and subclasses can overload the behavior.
Setvaluesforkeyswithdictionary: Sets the value of all key values in the recipient dictionary. The default implementation invokes Setvalue:forkey for each key-value pair: and nil instead of nsnull.
4, universal Access format: The-<key> method returns an object, scalar, or struct. -is<key> supports Boolean types.
5, the format of the universal setting value is set<key>:
If the property is a non-object type, you must also implement the meaning of the nil value. Setnilvalueforkey: The method is called when you try to set nil to a property.
As shown in the following example:
-(void) Setnilvalueforkey: (NSString *) Thekey {
if ([Thekey isequaltostring:@ "hidden"]) {
[Self setValue: @YES forkey:@ "hidden"];
}
else {
[Super Setnilvalueforkey:thekey];
}
}
6, Universal Collection Access format: Mutablearrayvalueforkey: or Mutablesetvalueforkey:
7, indexed Access format:-countof<key>
-objectin<key>atindex: or-<key>atindexes:
-get<key>:range:
As shown in the following example:
Listing 4 example-count<key> Implementation
-(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];
}
8, variable Index access:-insertobject:in<key>atindex: or –insert<key>atindexes:
-removeobjectfrom<key>atindex: or-remove<key>atindexes:
-replaceobjectin<key>atindex:withobject: or –replace<key>atindexes:with<key>:
-(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];
}
9, unordered Access format:-countof<key>
-enumeratorof<key>
-memberof<key>:
-(Nsuinteger) countoftransactions {
return [self.transactions Count];
}
-(Nsenumerator *) enumeratoroftransactions {
return [Self.transactions Objectenumerator];
}
-(Transaction *) Memberoftransactions: (Transaction *) AnObject {
return [Self.transactions Member:anobject];
}
10, variable unordered access:-ADD<KEY>OBJECT:OR-ADD<KEY>:
-remove<key>object:or-remove<key>:
-intersect<key>:
-(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];
}
11,key-value Validation: Verify
KVC provides a consistent API to validate property values.
Validation method: as follows:
Isting 1 Validation method declaration for the property name
-(BOOL) Validatename: (ID *) Iovalue error: (Nserror * __autoreleasing *) Outerror {
Implementation specific code.
return ...;
}
There are 3 possible outputs for the validation method:
1) The object value is valid, so return yes without changing the value and error
2) The object value is invalid and a valid value cannot be created. This returns no, and sets the error argument to a Nserror object table name for the reason.
3) The object value is invalid, but a valid value is created and returned. This returns YES. And does not set nserror, but needs to set a new iovalue.
-(BOOL) Validatename: (ID *) Iovalue error: (Nserror * __autoreleasing *) outerror{
The name must not is nil, and must is at least, characters long.
if ((*iovalue = = nil) | | ([(NSString *) *iovalue length] < 2)) {
if (outerror! = NULL) {
NSString *errorstring = nslocalizedstring (
@ "A person ' s name must is at least-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;
}
Important: If a validation method returns no, you need to first check whether the Outerror parameter is null, and if it is not NULL, the method should set Outerror to a valid Nserror object.
12, introduce a validation method: You can call the validation method directly by calling ValidateValue:forKey:error and specifying a key. The default implementation of the method searches for the receive class name matching Validate<key>error: The validation method, if this method is found, he will be called and return the result. If not found, returns YES.
Warning the implementation of:-set<key> should never invoke a validation method.
13, Automatic verification:
In general, KVC does not automatically perform validation-it is your responsibility.
Some other technologies do perform automatic validation: Core data automatically performs validation-when the context of the managed object is saved;
14, verify the scalar value:
-(BOOL) Validateage: (ID *) Iovalue error: (Nserror * __autoreleasing *) Outerror {
if (*iovalue = = nil) {
Trap this in Setnilvalueforkey.
An alternative might is to the create new NSNumber with value 0 here.
return YES;
}
if ([*iovalue Floatvalue] <= 0.0) {
if (outerror! = NULL) {
NSString *errorstring = nslocalizedstringfromtable (
@ "Age must is greater than zero" @ "person",
@ "Validation:zero age error");
Nsdictionary *userinfodict = @{nslocalizeddescriptionkey:errorstring};
Nserror *error = [[Nserror alloc] Initwithdomain:person_error_domain
Code:person_invalid_age_code
USERINFO:USERINFODICT];
*outerror = error;
}
return NO;
}
else {
return YES;
}
...
15, ensure KVC commitment:
16, if the attribute is a single value:
1) Implement-<key>-is<key> or have instance variables: <key> or _<key>
2) If the attribute is mutable, you should also implement the-set<key>
3)-set<key> should not perform validation.
4)-validate<key>:error should be implemented: if validation is appropriate for the key.
17, index is multi-valued:
Multi-valued properties for indexes:
1) Implement-<key>
2) or have an instance variable <key> or _<key>
3) or implement-countof<key> and-objectin<key>atindex: or-<key>atindexes: one of the
4) Optionally, you can implement-get<key>:range: to improve performance.
For a mutable index of ordered multivalued attributes, KVC promises to require your class
1) Implement –insertobject:in<key>atindex or-insert<key>:atindexes: one of the
2) Implement –removeobjectfrom<key>atindex: or one of the –remove<key>atindexes.
3) Optionally, you can implement-replaceobjectin<key>atindex:withobject or-replace<key>atindexes:with<key> to improve performance.
18, unordered multi-valued attribute:
For unordered multi-valued properties:
1) Implement-<key>
2) or with an instance variable:<key> or _<key>
3) or realize-countof<key>,-enumeratorof<key>, And-memberof<key>:.
For a mutable unordered to-many relationship, KVC compliance requires that your class Also
For variable unordered multivalued properties:
1) Implement one of the following 2 methods:-add<key>object:or-add<key>:.
2) Implement one of the following 2 methods:-remove<key>object:or-remove<key>:.
3) optional, you can implement-INTERSECT<KEY>: And-set<key>: To improve performance.
19, scalar and structure support:
The default implementations Valueforkey: and Setvalue:forkey: Non-object types are automatically wrapped, including scalar and struct types.
Once Valueforkey: A specific access method or instance variable has been determined, it checks the return type, and if not the object, NSNumber and Nsvalue objects are created and wrapped non-object values.
Similarly, Setvalue:forkey automatically extracts the xxxvalue of the Nsvalue or NSNumber object and assigns it to the attribute.
20, handling Nil value: Setvalue:forkey If you set the nil value to a non-object property, the recipient sends a SETNILVALUEFORKEY message, which, by default, causes a Nsvalidargumentexception exception. Subclasses can overload the behavior.
21, packaging and wrapping scalar value:
22, set Operator:
[Email protected]
All the set operators, except @count, require a keypath on the right side of the operator.
1) @avg
2) @count
3) @max: Take the maximum value, if the value that participates in the comparison is nil, the value is ignored.
4) @min: Nil value also ignored
5) @sum: Nil value also ignored
23, object operator:
1) @distinctUnionOfObjects: Example: Return
Nsarray *payees = [Transactions valueforkeypath:@ "@distinctUnionOfObjects. Payee"];
2) @unionOfObject:
Important: These 2 operators cause an exception if any of the leaf object values are nil.
24, array and set operator:
Prepare the array First:
Create the array that contains additional arrays.
Self.arrayoftransactionsarray = [Nsmutablearray array];
Add the array of objects used in the above examples.
[Arrayoftransactionsarray addobject:transactions];
ADD a second array of objects; This array contains alternate values.
[Arrayoftransactionsarrays addobject:moretransactions];
1) @distinctUnionOfArrays: Returns an array containing distinct objects, such as:
Nsarray *payees = [Arrayoftransactionsarrays valueforkeypath:@ "@distinctUnionOfArrays. Payee"];
2) Unionofarrays:
3) Distinctunionofsets:
25, accessor search implementation details:
26, the accessor searches for the format of the simple attribute:
27,setvalue:forkey: The search format:
1) First find the Access method Set<key>:
2) If not found, if the recipient's class method accessinstancevariablesdirectly returns Yes, the recipient searches the instance variable _<key> is<key> <key> or Is<key Search in this order
3) If it is found, use it to set the value.
4) If not found, call Setvalue:forundfinedkey:
28,valueforkey: The default search format:
1) Search the recipient's access methods sequentially get<key> <key> or is<key>. If found, it is called.
2) Otherwise, search the recipient's methods Countof<key>, Objectin<key>atindex: and <key>atindexes: If countof<key> Method and at least two other possible methods to find any one, a collection proxy object responds to all Nsarray methods that are returned.
3) Otherwise, the countof<key>, enumeratorof<key> and Memberof<key> are received. If 3 methods are found, a collection proxy object responds to all the Nsset methods that are returned.
4) Otherwise, if the recipient's class method accessinstancevariablesdirectly is yes, the receiver's class search instance variable _<key> _is<key> <key> or Is<key >. Find and return
5) If not found, Valueforundefinedkey:
29. The search format for an ordered collection of accessors:
Mutablearrayvalueforkey: The default search format is as follows:
1) the receiver class is searched for a pair of methods Insertobject:in<key>atindex and Removeobjectfrom<key>atindex: or Insert<key>: Atindexes and Remove<key>atindexes:
2) Otherwise, the recipient's class search Set<key>:
3) Otherwise, if the recipient's class method accessinstancevariablesdirectly is yes, the receiver's class search instance variable _<key> <key>. Find and return
4) If not found, call Setvalue:forundfinedkey:
30, the only search format for ordered collections:
Mutableorderedsetvalueforkey:
1) Search Methods Insertobject:in<key>atindex and Removeobjectfrom<key>atindex: or Insert<key>:atindexes and remove <key>atindexes:
2) Otherwise, the recipient's class search Set<key>:
3) Otherwise, if the recipient's class method accessinstancevariablesdirectly is yes, the receiver's class search instance variable _<key> <key>. Find and return
4) If not found, call Setvalue:forundfinedkey:
31. Search format for unordered collections:
Mytablesetvalueforkey:
1) Search Methods Add<key>object and Remove<key>object: or add<key> and remove<key>:
2) Otherwise, the recipient's class search Set<key>:
3) Otherwise, if the recipient's class method accessinstancevariablesdirectly is yes, the receiver's class search instance variable _<key> <key>. Find and return
4) If not found, call Setvalue:forundfinedkey:
Original URL: http://supershll.blog.163.com/blog/static/370704362012631103638204/
Key value Encoding KVC