KVO in Objective-C

KVO in Objective-C can be used to monitor the change of a certain property, and when the property changes, the observer will be notified. To use KVO, you need to use the -addObserver:forKeyPath:options:context: interface to register the monitor in the observer class. When the monitor object changes, the value of the object will be passed to the observer through the -observeValueForKeyPath:ofObject:change:context: method .

Principle of KVO

When an Object is observed, the system will dynamically create a subclass of Object, starting with NSKVONotifying, rewrite the set method of the property in the subclass, and call the -willChangeValueForKey: and -didChangeValueForKey: methods in the rewritten set method, if one When Object has no observers, the corresponding dynamic subclass will be deleted.

Create a new CustomClass class, this class has attributes string, string type

@interface CustomClass : NSObject

@property(nonatomic, strong) NSString *string;

@end

Add KVO monitoring in another class, and rewrite the observeValueForKeyPath:ofObject:change:context: method

CustomClass *obj = [[CustomClass alloc] init];
//NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld是枚举,可以同时监听旧值和新值
[obj addObserver:self forKeyPath:@"string" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
obj.string = @"str";
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    
    
    if ([keyPath isEqualToString:@"string"]) {
    
    
        NSString *res = change[NSKeyValueChangeNewKey];
        NSLog(@"%@", res);
    }
}

Add a breakpoint before obj.string = @“str”; line, when the breakpoint is broken, execute po object_getClass(obj) in the lldb debugger, the output is NSKVONotifying_CustomClass, execute po [obj class] , the output is CustomClass .

After obj is monitored, not only the set method is rewritten, but also the class method is rewritten in order to output the correct class type.

Add a method to remove the listener

[obj removeObserver:self forKeyPath:@"string"];

After this line of code is executed, enter po object_getClass(obj) and po [obj class] again, and the output is CustomClass. At this time, the KVO subclass has been released.

Objects that KVO can listen to

From the principle of KVO, it can be seen that its implementation is based on rewriting the set method, so member variables cannot be monitored through KVO, because member variables do not have a set method.

KVO can listen to property variables starting with @property, because property variables have a set method.

For the object declared readonly in .h, if it is declared as readwrite in the .m file, this attribute variable can also be monitored.

If a property does not want to be monitored, you can override the +automaticallyNotifiesObserversForKey: method and return NO in the method.

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
{
    
    
    if ([key isEqualToString:@"string"]) {
    
    
        return NO;
    } else {
    
    
        return YES;
    }
}

Guess you like

Origin blog.csdn.net/u011608357/article/details/127952688