iOS-模拟KVO

@interface Person : NSObject

@property (nonatomic, copy) NSString *name;

@end

@interface Person (KVO)

- (void)by_addObserver:(NSObject *)observer
            forKeyPath:(NSString *)keyPath
               options:(NSKeyValueObservingOptions)options
               context:(nullable void *)context;

@end

@implementation Person (KVO)

- (void)by_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context {
    NSString *originClassName = NSStringFromClass(self.class);
    NSString *newClassName = [@"CJ_NSKVONotifying_" stringByAppendingString:originClassName];
    
    Class kvoClass = objc_allocateClassPair([self class], [newClassName UTF8String], 0);
    
    class_addMethod(kvoClass, @selector(setName:), (IMP)setName, "v@:@");
    
    objc_registerClassPair(kvoClass);
    
    object_setClass(self, kvoClass);
    
    objc_setAssociatedObject(self, @"observer", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
}

void setName(id self, SEL _cmd, NSString *name) {
    Class kvoClass = [self class];
    
    object_setClass(self, class_getSuperclass([self class]));
    objc_msgSend(self, @selector(setName:), name);
    
    id objc = objc_getAssociatedObject(self, @"observer");
    
    NSDictionary *change = @{NSKeyValueChangeKindKey: @1,
                                                      NSKeyValueChangeNewKey:name};
    objc_msgSend(objc, @selector(observeValueForKeyPath:ofObject:change:context:), @"name",self, change,nil);
    object_setClass(self, kvoClass);
    
}

@end
Person *personModel = [[Person alloc] init];
    personModel.name = @"Cocoa";
    
    NSLog(@"%@",object_getClass(personModel));
    [personModel by_addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew| NSKeyValueObservingOptionOld context:nil];
    NSLog(@"%@",object_getClass(personModel));
    
    personModel.name = @"Cocoa Jason";
2022-03-03 10:26:52.096757+0800 dsadasdasdsa[10757:17330187] Person
2022-03-03 10:26:52.096907+0800 dsadasdasdsa[10757:17330187] CJ_NSKVONotifying_Person
2022-03-03 10:26:52.097098+0800 dsadasdasdsa[10757:17330187] {
    kind = 1;
    new = "Cocoa Jason";
}

你可能感兴趣的:(iOS-模拟KVO)