自定义KVO

1. 不调用实例变量的方法

2. 动态生成子类 (利用runtime生成:申请类,添加一些方法-set-class等方法,注册类 )

 

#import <Foundation/Foundation.h>

 

NS_ASSUME_NONNULL_BEGIN

 

@interface NSObject (FXKVO)

 

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

 

- (void)fx_observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context;

 

- (void)fx_removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

@end

 

NS_ASSUME_NONNULL_END

 

添加一个NSObject的分类,重写观察者方法

 

- (void)fx_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context{

    //1. 验证set方法

    [self judgeSetterMethodFromKeyPath:keyPath];

    //2. 动态生成子类

//    Class newClass = [self cre];

}

 

#pragma mark - 验证是否存在setter方法,如果不存在抛出异常(例如成员变量添加观察者会崩溃)

- (void)fx_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context{

    //1. 验证set方法

    [self judgeSetterMethodFromKeyPath:keyPath];

    //2. 动态生成子类

    Class newClass = [self creatChildClass];

    //3. 当前对象的类,isa指向newClass

    object_setClass(self, newClass);

}

 

#pragma mark - 动态生成子类

- (Class)creatChildClass{

 // LGKVO_LGPerson

    

    // 2. 动态生成子类

     

    NSString *oldName = NSStringFromClass([self class]);

    NSString *newName = [NSString stringWithFormat:@"%@%@", FXKVOPrefix, oldName];

    Class newClass    = objc_allocateClassPair([self class], newName.UTF8String, 0);

    

    //申请注册到内存中

    objc_registerClassPair(newClass);

    

    // 2.1 子类添加一些方法 class setter

    // class

    SEL classSEL = NSSelectorFromString(@"class");

    Method classM = class_getInstanceMethod([self class], classSEL);

    const char *type = method_getTypeEncoding(classM);

    class_addMethod(newClass, classSEL, (IMP)fx_class, type);

    

    return newClass;

}

猜你喜欢

转载自www.cnblogs.com/coolcold/p/12078068.html