• 细说KVO


    1.手动控制kvo的触发
    + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key; 返回NO ;

    然后在改变value前 调用[object willChangeValueForKey:@"key"];
    在改变value后, 调用[object didChangeValueForKey:@"key"] ;

    2.隔层kvo观察

    @interface Dog : NSObject

    @property(nonatomic)NSInteger age;

    @property(nonatomic)NSInteger *level;

    @end

    #import <Foundation/Foundation.h>

    #import "Dog.h"

    @interface Person : NSObject

    @property(nonatomic,strong)Dog *dog;

    @end

    #import "Person.h"

    @implementation Person

    -(instancetype)init{

        self = [super init];

        if (self) {

            _dog = [[Dog alloc]init];

        }

        return self;

    }

    +(NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key{

        NSSet *keyPath = [super keyPathsForValuesAffectingValueForKey:key];

        if ([key isEqualToString:@"dog"]) {

            NSArray *arr = @[@"_dog.level",@"_dog.age"];

            keyPath = [keyPath setByAddingObjectsFromArray:arr];

        }

        return keyPath;

    }

    @end

    //设置观察

      self.person = [[Person alloc] init];

     [self.person addObserver:self forKeyPath:@"dog" options:NSKeyValueObservingOptionOld context:nil];

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

    {

        NSLog(@"change:%@",change);

    }

    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event  {

        self.person.dog.age++;

    }


    2.KVO的底层实现

    #import "NSObject+PRKVO.h"

    #import <objc/runtime.h>

    @implementation NSObject (PRKVO)

    -(void)PR_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context

    {

        //1.自定义一个NSKVONotifying_Person子类

        NSString *oldClassName = NSStringFromClass(self.class);

        NSString *newClassName = [@"PRKVO_" stringByAppendingString:oldClassName];

        //创建一个类

        Class MyClass = objc_allocateClassPair(self.class, newClassName.UTF8String, 0);

        //注册该类

        objc_registerProtocol(MyClass);

        

        //2.动态修改

        object_setClass(self, MyClass);

        

        //3.添加setName方法,重新父类setName

        class_addMethod(MyClass, @selector(setName:), (IMP)haha, "v@:@");

        

    }

    void haha(id self,SEL _cmd,NSString *newName){

        NSLog(@"!%@",newName);

    }

     
    
    


  • 相关阅读:
    第2章 ActionScript教程 显示
    第0章 ActionScript教程 Flash相关概念
    PHP中可速查的知识点
    ActionScript3中的Int64与ByteArray转换
    第9章 ActionScript教程 应用程序国际化
    关于一个经典的委托和事件的问题 关于老鼠 猫 主人问题 帝都
    页面导入样式时,使用link和@import有什么区别
    圣杯布局和双飞翼布局的理解和区别,并用代码实现
    Mac电脑 python3.9 连接SQL Server报错
    MAC电脑如何将常规视频中音频提取出来(转换格式并调整采样频率),并利用python结合讯飞语音识别文字
  • 原文地址:https://www.cnblogs.com/PJXWang/p/8431666.html
Copyright © 2020-2023  润新知