In iOS development, KVC and KVO are often used. You can use KVC to assign values to an object's properties and get the object's property values, and you can use KVO to listen for changes in the object's property values. A brief introduction to KVC and KVO.
One: Key value encoding (KVC)
KVC, full name key value Coding (key code), is a feature of the OC Language, which uses KVC to dynamically read and write the properties of an object.
The KVC method is provided by the Nskeyvaluecoding protocol, and NSObject has implemented the protocol, so that almost all objects in OC can use KVC operations. Common methods of KVC operation are:
(1) Setting property values
Setvalue:value Forkey:key (for simple paths, i.e. direct attributes)
Setvalue:value Forkeypath:key (for complex paths, i.e. indirect properties)
(2) Get property values
Valueforkey:key (property value for getting a simple path)
Valueforkeypath:key (used to get property values for complex paths)
Use the code to see the specific uses of KVC:
Two classes are the dog class and the person class, respectively.
Dog.h
1 #import <foundation/foundation.h>2 3 @interface dog:nsobject4 5 @property (nonatomic, copy) NSString *name;6 7 @ End
Dog.m
1 #import "Dog.h" 2 3 @implementation Dog4 5 @end
Person.h
1 #import <Foundation/Foundation.h> 2 3 @class Dog; 4 5 @interface person:nsobject 6 7 @property (Nona Tomic, copy) NSString *name; 8 @property (nonatomic, copy) NSString *sex; 9 @property (nonatomic, strong) Dog *dog;11 @end
Person.m
1 #import "Person.h" 2 3 @implementation Person4 5 @end
Use of KVC:
1 person *person = [[Person alloc] init]; 2 //KVC setting value 3 [person setvalue:@ "Jim" forkey:@ "name"]; 4 [Person setvalue:@ ' boy ' forkey:@ ' sex ']; 5 6 //KVC Gets the value 7 NSLog (@ "name =%@ sex =%@", [Person valueforkey:@ "name"],[person valueforkey:@ "Sex"]); 8 9 Dog *dog = [[Dog alloc] init];10 person.dog = dog;11 //kvc set Complex path value [person setvalue:@ ' Teddy ' forkeypath:@ "Dog.name"];13 //kvc get complex path values of NSLog (@ "Dog name =%@", [person valueforkeypath:@] Dog.name "]);
As you can see, KVC uses the corresponding function to set the value and get the value. So, how does KVC find a property to read? KVC follows the following rules, assuming that you want to read the Name property:
(1) Setting Properties: SetName method is preferred, if not, the member variable _name is searched, if not found, the member variable name is searched, and if not found, the Setvalue:forundefinekey: method is called.
(2) Read attribute: GetName method is preferred, if not, the member variable _name is searched, if not found, the member variable name is searched, and if not found, the Valueforundefinekey: method is called.
Second: The use of KVC in Setvaluesforkeyswithdictionary:
There is a very important method in KVC: Setvaluesforkeyswithdictionary:dict, which can map a dictionary to an object, eliminating the need to assign a value to object one by one.
An example of using setvaluesforkeyswithdictionary:dict:
Student.h
1 #import <Foundation/Foundation.h> 2 3 @interface student:nsobject 4 5/** 6 * Study No. 7 */8 @pro Perty (nonatomic, copy) NSString *num; 9/**10 * name */12 @property (nonatomic, copy) nsstring *name;13/**14 * height */16 @ Property (nonatomic, assign) float height;17/**19 * two ways to initialize *21 */22-(instancetype) Initwithdict: (nsdictionary *) dict;23 + (Instancetype) stuwithdict: (nsdictionary *) dict;24 @end
Student.m
1-(Instancetype) Initwithdict: (Nsdictionary *) dict{2 if (self = [super init]) {3 [self SETVALUESFORKEYSWITHDICTIONARY:DICT]; 4 } 5 return self; 6} 7 8 + (Instancetype) stuwithdict: (Nsdictionary *) Dict 9 {10
Initialize an object with a dictionary
1-(void) Initstudent 2 {3 nsdictionary *dict = [nsdictionary dictionarywithobjectsandkeys:4 @ "Tom", @ "name", 5< c10/>@ "", @ "num", 6 @ "170.0", @ "height", 7 Nil], 8 Student *stu = [[Student alloc] initwithdict:dict]; 9 NSLog (@ "name =%@ num =%@ height =%f", stu.name,stu.num,stu.height); 10}
The principle of setvaluesforkeywithdictionary:dict
In fact, the Setvaluesforkeywithdictionary:dict method is to traverse Dict and Invoke Setvalue:forkey: method for each key value in Dict. You can simulate setvaluesforkeywithdictionary:dict in the following ways:
1-(void) SetProperty: (Nsdictionary *) dict2 {3 for (NSString *key in [Dict AllKeys]) 4 {5 nsstring *value = [di CT objectforkey:key];6 [self setvalue:value forkey:key];7 }8}
When called:
1-(Instancetype) Initwithdict: (nsdictionary *) dict{2 if (self = [super init]) {3 //[self Setvaluesforkeyswithdictionary:dict];4 [self setproperty:dict];5 }6 return self;7}
And the Setvaluesforkeywithdictionary:dict function is the same.
Use Setvaluesforkeywithdictionary:dict a place to be aware of
A crash occurs when there is a value in the dictionary, and the object does not have a corresponding property. For example, the new dictionary is as follows:
1-(void) Initstudent 2 {3 nsdictionary *dict = [nsdictionary dictionarywithobjectsandkeys:4 @ "Tom", @ "name", 5< c3/>@ "", @ "num", 6 @ "170.0", @ "height", 7 @ "boy" @ "Sex", nil]; 8 Student *stu = [[Student alloc] INITWITHDICT:DICT]; 9 NSLog (@ "name =%@ num =%@ height =%f", stu.name,stu.num,stu.height); 10}
There is a sex attribute in the dictionary, but there is no property in the Studeng object, and a crash occurs. Workaround:
Implement the Setvalue:forundefinekey: method to handle cases where no attributes are present in the method.
Add code in Student.h:
1-(void) SetValue: (ID) value Forundefinedkey: (NSString *) key;
Add code in STUDENT.M:
1-(void) SetValue: (ID) value Forundefinedkey: (NSString *) Key2 {3 4}
When there are no attributes, the Setvalue:forundefinekey: method is called. Because this method has not been processed, this situation does not handle and does not crash. Note that: Setvalue:forundefinekey: The method is widely used, for example, a key value in a dictionary is an ID, but in OC the ID is a keyword, which can also be handled in the Setvalue:forundefinekey: method.
Three: Key-value monitoring (KVO)
KVO Full name Key Value observing. The KVO can be used to separate the view component from the data model, and the view acts as a listener, and the listener can do the corresponding processing when the model's property values change. The Kvo method is provided by the Nskeyvalueobserving protocol, and the same nsobject already implements the protocol, so that almost all objects can use KVO.
Common ways to use KVO operations are as follows:
Register the Listener for the path: AddObserver:forKeyPath:option:context:
To delete the listener that made the path: Removeobserver:forkeypath:
How to trigger the listener: ObserveValueForKeyPath:ofObject:change:context:
An example of a kvo:
There are two classes: the Dog class and the People class
Dog.h
1 #import <foundation/foundation.h>2 3 @interface dog:nsobject4 5 @property (nonatomic, copy) NSString *name;6 7 @ End
Dog.m
1 #import "Dog.h" 2 3 @implementation Dog4 5 @end
People.h
1 #import <Foundation/Foundation.h> 2 3 @class Dog; 4 5 @interface people:nsobject 6 7 @property (Nona Tomic, copy) NSString *name; 8 @property (nonatomic, strong) Dog *dog; 9 @end
People.m
1 #import "People.h" 2 #import "Dog.h" 3 4 @implementation people 5 6/** 7 * increased monitoring of DOG during initialization 8 * 9 */10-(void) Setdog: (Dog *) dog11 { _dog = dog;13 [self.dog addobserver:self forkeypath:@ ' name ' options: Nskeyvalueobservingoptionnew context:nil];14}15/**16 * override Observevalueforkeypath Method */18-(void) Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object change: (nsdictionary<nsstring *,id> *) Change Context: (void *) context19 { if ([KeyPath isequaltostring:@ "name"]) { NSLog (@ "newName =%@", [Change objectforkey:@ "new"]); }23}24-(void) dealloc26 { //Remove listener [Self.dog removeobserver:self forkeypath:@ "Name"];29}30 @end
To test the KVO function:
1-(void) Testkvo 2 {3 people *people = [[People alloc] init]; 4 people.name = @ "Tom"; 5 dog *dog = [[Dog all] OC] init]; 6 Dog.name = @ "Teddy"; 7 people.dog = Dog; 8 9 //After performing this step, the function that will trigger the listener (Observevalueforkeypath) Dog.name = @ "Testchange"; 11}
In code, when you modify the Name property of the dog, the listener is triggered, which is
Observevalueforkeypath: (NSString *) KeyPath Ofobject: (ID) object change: (nsdictionary<nsstring *,id> *) Change Context: (void *) the context method.
Introduction to KVC and KVO in iOS development