zoukankan      html  css  js  c++  java
  • 细说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);

    }

     
    
    


  • 相关阅读:
    GO语言面向对象06---面向对象练习01
    GO语言面向对象05---接口的多态
    GO语言面向对象04---接口的继承
    GO语言面向对象03---接口与断言
    GO语言面向对象02---继承
    Go语言练习---判断闰年以及根据现在的秒数求现在的年月日
    [操作系统] 线程管理
    [操作系统] 进程的状态
    [操作系统] 进程控制块
    关于这次计算机设计大赛
  • 原文地址:https://www.cnblogs.com/PJXWang/p/8431666.html
Copyright © 2011-2022 走看看