美文网首页
iOS-模拟KVO

iOS-模拟KVO

作者: CocoaJason | 来源:发表于2022-03-07 16:59 被阅读0次
    @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";
    }
    
    

    相关文章

      网友评论

          本文标题:iOS-模拟KVO

          本文链接:https://www.haomeiwen.com/subject/pjvyrrtx.html