美文网首页
KVO与指针作为参数的传递和接收

KVO与指针作为参数的传递和接收

作者: 流光还铅华 | 来源:发表于2017-12-29 20:03 被阅读46次
    最近写代码写的有点飘,回过头来看ios的基础发现我对KVO机制的用法和传参居然不太熟悉。
    KVO是Key Value Observe的缩写,中文是键值观察。这是一个典型的观察者模式,观察者在键值改变时会得到通知。
      KVO的使用也很简单,就是简单的3步。
      1.注册需要观察的对象的属性addObserver:forKeyPath:options:context:
      2.实现observeValueForKeyPath:ofObject:change:context:方法,这个方法当观察的属性变化时会自动调用
      3.取消注册观察removeObserver:forKeyPath:context:
    
    注册观察者
    - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
    //----------使用及参数讲解----------
    //被观察者对象调用此方法注册监听
    //observer  观察者对象
    //keyPath   被观察者对象的属性名
    //options   有四种事件属性,通常使用 NSKeyValueObservingOptionNew观察值的改变
    //context   扩展属性,传递一个指针(变量指针、对象指针、函数、block)
    
    监听事件
    - (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context;
    //----------使用及参数讲解----------
    //在观察者类中实现此方法
    //keyPath    被观察者属性名
    //object     被观察者对象本身
    //change     被观察者前后改变的属性值
    //context    扩展参数
    

    KVO的使用其实超级简单,这里就不过多说明了。主要讲一下context参数的使用。
    在注册方法中传入context参数,当监听方法被回调时得到的context参数与注册方法中传入的context参数是同一个对象。而context参数是任意的指针参数,也就是说满足传入值要求的参数必须是个指针,那么相应的监听方法中就要以指针形式去接收数据。

    下面讲解4种类型指针的传入与对应的解析:1、基本数据类型 2、对象类型 3、函数 4、block块函数
    1、基本数据类型
        //注册观察者
        self.person= [[Person alloc]init];
        self.person.age = 3;
        self.param = 5;
        [self.person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:&param];
        //改变属性即触发监听
        self.person.age = 20;
    
    
    //监听事件
    - (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context{
            NSLog(@"%d",*(int*)context);
    }
    //结果为5
    
    2、对象类型
    //注册观察者
     _dict = [NSMutableDictionary dictionary];
     _dict[@"cheshi"]= @"测试";
     [self.person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:(__bridge void * _Nullable)(_dict)];
    //改变属性即触发监听
     self.person.age = 20;
    
    //监听事件
    - (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context{
         id res = (__bridge id)(context);
         if ([res isKindOfClass:[NSMutableDictionary class]]) {
              NSLog(@"%@",res);
         }
    }
    //结果为:{cheshi = "\U6d4b\U8bd5";}
    
    
    3、函数
    void test1(){
        NSLog(@"test1函数被触发了");
    };
    
    //注册观察者
    [self.person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:test1];
    //改变属性即触发监听
     self.person.age = 20;
    
    //监听事件
    - (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context{
        void (*test)(void) = context;
        test();
    }
    //执行结果:test1函数被触发了
    
    4、block块函数
    //声明block
    typedef void (^CheshiBlock)(void);
    
     CheshiBlock cheb  = ^(void) {
            NSLog(@"block触发");
        };
    //注册观察者
    [self.person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:(__bridge void * _Nullable)(cheb)];
    //改变属性即触发监听
     self.person.age = 20;
    
    //监听事件
    - (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context{
       CheshiBlock bbb = (__bridge CheshiBlock)(context);
        bbb();
    }
    //执行结果:block触发
    

    最后注意一点,注册了观察者事件,一定要在合适的地方移除事件。
    转载请注明出处@@

    相关文章

      网友评论

          本文标题:KVO与指针作为参数的传递和接收

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