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 <NSKeyValueChangeKey, id>*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";
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容