Introduction to the

KVO is a set of event notification mechanisms provided by Apple. Its full name is KeyValueObserving. Allows an object to listen for changes to specific properties of another object and to receive an event when the change occurs. Because of the way KVO is implemented, this applies to properties, and objects that inherit from NSObject generally support KVO by default.

Basic usage

@interface YZPerson : NSObject

@property (nonatomic,assign) int age;
@property (nonatomic,strong) NSString  *name;

@end
Copy the code
- (void)viewDidLoad { [super viewDidLoad]; self.person = [[YZPerson alloc] init]; / / registered observers NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld; [self.person addObserver:self forKeyPath:@"name" options:options context:@"1111"]; } // Callback method. When the value of the property of the listener changes, - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {NSLog(@" listening to %@ attribute change - %@ - %@", object, keyPath, change, context); } -(void)dealloc{// remove listener [self.person removeObserver:self forKeyPath:@"name"]; }Copy the code

Note: Repeated removal of the listener will crash because it has been removed and cannot be found. So, make sure add and remove are paired.

KVO can listen for changes to individual attributes as well as collection objects. The proxy object is obtained through methods such as KVC’s mutableArrayValueForKey:, and when the internal object of the proxy object changes, the method KVO listens for is called back. Collection objects contain NSArray and NSSet.

The underlying principle

KVO is implemented using isA-Swizzling technology.

1. At Runtime, create an intermediate class NSKVONotifying_xxx based on the original class. This intermediate class isa subclass of the original class, and dynamically change the current object’s isa to point to the intermediate class. 2. The _NSSetXXXValueAndNotify function is called when an object property is modified. This is going to call willChangeValueForKey:, then call the original setter method of the parent class to change the value, and finally didChangeValueForKey:, Its internal will trigger the listener (Oberser) surveillance method observeValueForKeyPath: ofObject: change: context:, and the method of class rewritten, return to the original class class.

  • About intermediate Classes

KVO is applied to different objects of the same class, because the dynamic points to the respective intermediate classes, which have different class objects. So you can accurately listen for specific properties of different objects. The name of the class given by [instance class] is the same (that is, the class to which the instance belongs), not the name of the middle class.

  • On the setter

When you change a property, you do so by calling its setter. After adding KVO listening point setter to _NSSetObjectValueAndNotify function. If there is no setter to change the value of the property, or if there is no setter for the property, then the KVO will not be fired.

  • Manually trigger KVO

Manually calling the object’s willChangeValueForKey and didChangeValueForKey methods also triggers the listening callback method, but the property values remain the same. Because the property is not assigned.

[self.person willChangeValueForKey:@"name"];
[self.person didChangeValueForKey:@"name"];
Copy the code

Compare KVC and NSNotificationCenter

KVC, also known as key-value Coding, is an informal Protocol that uses strings (keys) to access an object instance variable. Rather than using explicit access methods like setters and getters.

Both KVC and KVO belong to key-value programming, and the underlying implementation mechanism is ISA-Swizzing.

Both KVO and NSNotificationCenter are implementations of the observer pattern in iOS. Both are one-to-many, but for direct interaction between objects, notification is much more obvious, and notificationCenter is required as an intermediate interaction. The advantage of notification is that listening is not limited to attributes, but can also be listened on a wide range of state changes.

KVO is non-invasive to the object being listened to and can be listened on without modifying its internal code.

other

  • Modify the selected and default images of UIPageControl with KVC

(Default is not allowed to change)

  [self.pageControl setValue:currentImage forKey:@"_currentPageImage"];
  [self.pageControl setValue:pageImage forKey:@"_pageImage"];
Copy the code
  • How to KVO NSMutableArray

KVO is normally triggered only by changing the value by calling the set method. But when you call an NSMutableArray’s addObject or removeObject family of methods, it does not fire its set method. In order to implement the KVO of NSMutableArray, we have the following methods:

@property (nonatomic, strong) NSMutableArray *arr; [[self mutableArrayValueForKey:@"arr"] addObject:item]; [[self mutableArrayValueForKey:@"arr"] removeObjectAtIndex:0];Copy the code