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

2017-12-29  本文已影响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触发

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

上一篇下一篇

猜你喜欢

热点阅读