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

最近写代码写的有点飘,回过头来看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触发

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

最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 2,210评论 0赞 9
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,746评论 30赞 472
  • 上半年有段时间做了一个项目,项目中聊天界面用到了音频播放,涉及到进度条,当时做android时候处理的不太好,由于...
    DaZenD阅读 3,139评论 0赞 26
  • 1.写一个NSString类的实现 +(id)initWithCString:(c*****t char *)nu...
    韩七夏阅读 3,893评论 2赞 37
  • __block和__weak修饰符的区别其实是挺明显的:1.__block不管是ARC还是MRC模式下都可以使用,...
    LZM轮回阅读 3,648评论 0赞 6

友情链接更多精彩内容