First, the KVO

1, an overview of the

The full name of KVO is KeyValueObserving, commonly known as “key value monitoring”, which can be used to monitor the change of the property value of an object.

KVO is an event notification mechanism provided by Apple. Both KVO and NSNotificationCenter are implementations of the observer mode in iOS. The differences are as follows: NSNotificationCenter can be one-to-many, while KVO is one-to-one.

2. Use of KVO

There are three steps to using KVO:

  • Register KVO listening

Through [addObserver: forKeyPath: options: context:] registered KVO method, so that can receive the keyPath attributes change events;

  • KVO listening implementation

Through the method of [observeValueForKeyPath: ofObject: change: context:] realize KVO listening;

  • Remove KVO listening

When don’t need to listen to, through the method of [removeObserver: forKeyPath:], removing listening;

/ / 1. Add a property of the object KVO [p addObserver: self forKeyPath: @ "name" options: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil]; /** keyPath: the key object of the observed attribute. Change: the change object of the observed attribute. Context: Context */ - (void) observeforkeypath :(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {NSLog(@" heard the %@ property changed ", object, keyPath); NSLog(@"%@", change); }Copy the code

3. Code example implementation

Register listening:

/ / add KVO listening to person1 object attribute the change of the age NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld; [self.person1 addObserver:self forKeyPath:@"age" options:options context:@"123"];Copy the code

KVO listening implementation:

// When the listener's property value changes, - (void) observeforkeypath :(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {NSLog(@" monitoring %@ - %@ - %@", object, keyPath, change, context); }Copy the code

Remove KVO listener:

- 
    [self.person1 removeObserver:self forKeyPath:@"age"];
}
Copy the code

4. Principle of KVO

The essence of KVO is to change the call to setter methods:

  1. Dynamically generate a subclass using the Runttime API and have instance object’s ISA point to this new subclass;
  2. When modifying the properties of an Instance object, Foundation’s _NSSetXXXValueAndNotify function is called.
  • I’ll call the willChangeValueForKey method,
  • Call the original setter method of the parent class
  • The last call didChangeValueForKey, internal will trigger the listener (Oberser) surveillance methods (observeValueForKeyPath: ofObject: change: context:);

_NSSetXXXValueAndNotify Internal implementation principle

  • I’ll call the willChangeValueForKey method,
  • Call the original setter method of the parent class
  • The last call didChangeValueForKey, internal will trigger the listener (Oberser) surveillance methods (observeValueForKeyPath: ofObject: change: context:);

Calling KVO manually involves two steps:

  1. Modify the class methods automaticallyNotifiesObserversForKey return values;
  2. Two methods are used to call KVO: willChangeValueForKe before the property changes and didChangeValueForKey after the change.
/ / in the class member variables + (BOOL) automaticallyNotifiesObserversForKey: (nsstrings *) key {the if ([key isEqualToString: @ "age"]) {return NO; } return [super automaticallyNotifiesObserversForKey:key]; } - (void)setAge:(int)age { if ( _age ! = age ) { [self willChangeValueForKey:@"age"]; _age = age; [self didChangeValueForKey:@"age"]; }}Copy the code

Second, the KVC

1, an overview of the

The full name of KVC is KeyValueCoding, commonly known as “key value coding”, you can access a property through a key;

KVC provides a mechanism to access its attribute methods or member variables indirectly. You can access corresponding attribute methods or member variables through strings.

2. Common apis include:

- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (void)setValue:(id)value forKey:(NSString *)key;
- (id)valueForKeyPath:(NSString *)keyPath;
- (id)valueForKey:(NSString *)key;
Copy the code

3. Principle of setValue:forKey

KVC assignment principle:

  • First, the method will be searched according to the order of setKey and _setKey, find the method, call the method directly and assign the value;
  • Method was not found, then the call + (BOOL) accessInstanceVariablesDirectly;
  • If accessInstanceVariablesDirectly method returns YES, according to _key, _isKey, key member variables, isKey sequential search, find direct assignment, find throw an exception;
  • If accessInstanceVariablesDirectly method returns NO, an exception is thrown directly;

AccessInstanceVariablsDirectly method is the default return value is the YES;

ValueForKey: principle

KVC value principle:

  • First, the system searches for methods in the order of getKey, key, isKey, and _key to find the directly called value
  • If not found, then check the + (BOOL) accessInstanceVariablesDirectly return values, if return NO, an exception is thrown directly;
  • If YES is returned, the member variables are searched in _key, _isKey, key, and isKey order. If YES is found, the value is taken.
  • If not found, an exception is thrown;

Reprint | the original address