Introduction to KVC and KVO

Summary

1, KVC: key encoding, members, management object using the string attribute:
2, KVO key monitoring, an observer mode, monitoring changes in the property, separation can be achieved and the data model of UI


Key value encoding KVC (NSKeyValueCoding)

Role: dynamic management of object attributes of reading and writing operations.

KVC’s method of operation is provided by the NSKeyValueCoding protocol, and NSObject implements the protocol, which means that almost all objects in OC support KVC operations.

Usage mode:

  • Simple path

Set value: [object setValue: attribute value forKey:, property name]
value: [object valueForKey: property name]

  • Composite path

Set value: [object setValue: attribute value, forKeyPath: attribute path]
value: [object valueForKeyPath: attribute path]


Example:

We define a Person class and declare an attribute of name

Person.h file

#import < Foundation/Foundation.h> @interface Person: NSObject, @property (copy, nonatomic), NSString, *name; @end

We use KVC in the main program to control the fetch and set operations of the name

#import < Foundation/Foundation.h> #import "Person.h" int main (int argc, const char * argv[] @autoreleasepool) {{Person *person = [Person new]; [person setValue:@ "LOLITA" forKey:@ "name"]; NSLog (@ -->% @ "[person, valueForKey:@]" name ");} return 0;}

Operation result

Introduction to KVC and KVO
takes name

In fact, KVC can not only set person attributes, but also person member variables, either public or private

We add new member variables to the Person class

Person.h

#import < Foundation/Foundation.h> @interface Person: NSObject {@private NSString *_sex; @public CGFloat _height;} @property (copy, nonatomic) NSString *name; @end

Main program

#import < Foundation/Foundation.h> #import "Person.h" int main (int argc, const char * argv[] @autoreleasepool) {{Person *person = [Person new]; [person setValue:@ "fale" forKey:@ "sex"]; NSLog (@ --> [person, valueForKey:@% @ "" sex ""); [person setValue:@ "170" forKey:@ "_height"]; NSLog (@ --> [person, valueForKey:@% @ "" height "");} return 0;}

Operation result

Introduction to KVC and KVO,
, sex, and height

We can see that the members of the Person variable is _sex and _height, if you set the value and values of the “_” effect is the same, this set of mechanisms related with KVC

  • Setting: priority for the setter method, if not the method for member variables _a, if still does not exist, is looking for the member variable a, if we don’t find it will call the class’s setValue:forUndefinedKey: method, and whether these methods, member variables are private or public or even read-only can be set correctly;

Priority is: setter method, –> _a–> a–> setValue:forUndefinedKey: method

  • Value: priority for the getter method, if the method is not found for member variables _a, if still does not exist, is looking for the member variable a, if you still have not found the will for this class of valueforUndefinedKey: method

Priority is: getter method, –> _a–> a–> valueforUndefinedKey: method


Composite path

If there is a Accont class in Person that represents the account balance, how do you use KVC?

Account.h file

#import < Foundation/Foundation.h> @interface; Account: NSObject {float _balance;} / / account balance @end

Person.h file

#import < Foundation/Foundation.h> #import "Account.h" @interface Person: NSObject @property (strong, nonatomic) Account *account; / / account balance @end

Person.m file

#import "Person.h" @implementation Person (instancetype) init{if (self = [super init]) {self.account [Account = new]; / / to initialize the object return self @end}};

Main program

#import < Foundation/Foundation.h> #import "Person.h" int main (int argc, const char * argv[] @autoreleasepool) {{Person *person = [Person new]; [person setValue:@ "1234.6" forKeyPath:@ "account.balance"]; NSLog (@ --> [person, valueForKeyPath:@% @ "" account.balance "");} return 0;}

Operation result:

Introduction to KVC and KVO
composite path usage



Key value listener KVO (NSKeyValueObserving)

Role: separating UI from data model

KVO is a kind of observer pattern, can change the value of an object attribute monitor, when the property value changes, as the listener can respond accordingly, using this model, we can realize the communication between Module and View in MVC mode, i.e. when the Module changes UI, as an observer can change.

Usage mode:

  1. Register as observer: addObserver:, forKeyPath:, options:, context:
  2. Overwrite monitor callback method: observeValueForKeyPath: ofObject: change: context:
  3. Log off viewer: removeObserver: forKeyPath or removeObserver: forKeyPath: context:

Example:

Here, the controller is used as an observer to observe the properties of a model to mask the use of KVO

First, we create a project and build a new data model

#import < Foundation/Foundation.h> #import < UIKit/UIKit.h> @interface; DataModule: NSObject {NSString *_title;} / / @end title

Define a label inside the ViewController to represent the display on the UI

Self.label = [[UILabel alloc] initWithFrame:CGRectMake ([UIScreen mainScreen].bounds.size.width, 0, 0, 30)]; @ self.label.text = "a value"; self.label.textAlignment = NSTextAlignmentCenter; self.label.font = [UIFont systemFontOfSize:16]; self.label.center = self.view.center; [self.view addSubview:self.label];

Step 1: initialize the model and register the controller as the observer of the model

Self.module = [DataModule new]; [self.module addObserver:self forKeyPath:@ "title" options:NSKeyValueObservingOptionNew context:nil]; / / registered as observer

Step two: overwrite the listening callback for KVO

- (void) observeValueForKeyPath: (NSString *) keyPath ofObject: (ID) object change: (NSDictionary< NSKeyValueChangeKey, id> change (void * *) context: context{if ([keyPath) isEqualToString:@ "title"]) {if (object = = self.module) {self.label.text = [change objectForKey:@ new}else{[super observeValueForKeyPath:keyPath ofObject:object; change:change context:context]}}};

Step three: manually cancel the viewer

- (void) dealloc{/ removeObserver:self forKeyPath:@ cancellation observer [self.module "title"];}

Thus, when the data model changes, we can listen and change on the UI

/ / after 3 seconds, the dispatch_after value changes in the data model of title (dispatch_time (DISPATCH_TIME_NOW (int64_t) (3 * NSEC_PER_SEC)), dispatch_get_main_queue ([self.module), ^{setValue:@ "a new value" forKey:@ "title"];});

Operation result

Introduction to KVC and KVO
KVO example

Note: be sure to remove the viewer at the right time



Reference material

IOS development series –Objective-C KVC, KVO