iOS KVO详解

一、概述

KVO<NSKeyValueObserving>,是一个非正式协议,提供了一个途径,使对象(观察者)能够观察其他对象(被观察者)的属性,当被观察者的属性发生变化时,观察者就会被告知该变化。指定一个被观察对象(例如 A 类),当对象某个属性(例如 A 中的字符串 name)发生更改时,对象会获得通知,并作出相应处理;【且不需要给被观察的对象添加任何额外代码,就能使用 KVO 机制】

二、使用方法

系统框架已经支持KVO,所以程序员在使用的时候非常简单。

1、添加观察者:

- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;

2、实现观察响应方法:

- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary*)change context:(nullable void *)context;

3、移除观察者:

- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

假设一个场景,股票的价格显示在当前屏幕上,当股票价格更改的时候,实时显示更新其价格。

1.定义Model,

    @interface StockData : NSObject {
        NSString * stockName;
        Nsstring * price;
    }
    @end
    @implementation StockData
    @end
#import "KVOViewController.h"

@interface KVOViewController ()
{
    StockData *stockForKVO;
    UILabel *myLabel;
}
@end

@implementation KVOViewController


- (void)viewDidLoad
  {
      [super viewDidLoad];
      //2.定义此model为Controller的属性,实例化它,监听它的属性,并显示在当前的View里边
      stockForKVO = [[StockData alloc] init];
      [stockForKVO setValue:@"searph" forKey:@"stockName"];
      [stockForKVO setValue:@"10.1" forKey:@"price"];
      [stockForKVO addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
   
      myLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 100, 30 )];
      myLabel.backgroundColor = [UIColor redColor];
      myLabel.text = [stockForKVO valueForKey:@"price"];
      [self.view addSubview:myLabel];
     
      UIButton * b = [UIButton buttonWithType:UIButtonTypeCustom];
      b.frame = CGRectMake(10, 100, 100, 30);
      [b addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
      [b setTitle:@"测试" forState:(UIControlStateNormal)];
      [self.view addSubview:b];
//      self.view.backgroundColor = [UIColor greenColor];
   
  }
-(void) buttonAction
{
    [stockForKVO setValue:@"20.0" forKey:@"price"];
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if([keyPath isEqualToString:@"price"])
    {
        myLabel.text = [stockForKVO valueForKey:@"price"];
    }
}
- (void)dealloc
{
    [stockForKVO removeObserver:self forKeyPath:@"price"];
}

@end

  
/**
 options参数说明:
  NSKeyValueObservingOptionNew   拿到新值
  NSKeyValueObservingOptionOld   拿到旧值
 NSKeyValueObservingOptionInitial   注册就会发一下通知,改变后还会发
 NSKeyValueObservingOptionPrior   改变之前发一次,改变后发一次
 */

三、实现原理

KVO是通过isa-swizzing技术实现的。

运行时根据原来创建一个中间类,这个中间类是原来的子类,NSKVONotifying_xx

并动态修改当前对象的isa指针指向中间类

并且将class方法重写,返回原类的class

setter方法里面

调用willChangeValueForKey

调用原来的setter实现

调用didChangeValueForKey

didChangeValueForKey:内部会调用observerValueForKeyPath方法

当观察对象移除所有的监听后,会将观察对象的isa指向原来的的类。

当观察对象的监听全部移除后,动态生成的类不会注销,而是留下下次观察时候再使用,避免反复创建中间子类

拓展

1.KVC 与 KVO 的不同?

KVC(键值编码),即 Key-Value Coding,一个非正式的 Protocol,使用字符串(键)访问一个对象实例变量的机制。而不是通过调用 Setter、Getter 方法等显式的存取方式去访问。
KVO(键值监听),即 Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,对象就会接受到通知,前提是执行了 setter 方法、或者使用了 KVC 赋值。

2.和 notification(通知)的区别?

notification 比 KVO 多了发送通知的一步。
两者都是一对多,但是对象之间直接的交互,notification 明显得多,需要notificationCenter 来做为中间交互。而 KVO 如我们介绍的,设置观察者->处理属性变化,至于中间通知这一环,则隐秘多了,只留一句“交由系统通知”,具体的可参照以上实现过程的剖析。

notification 的优点是监听不局限于属性的变化,还可以对多种多样的状态变化进行监听,监听范围广,例如键盘、前后台等系统通知的使用也更显灵活方便。

3.与 delegate 的不同?

和 delegate 一样,KVO 和 NSNotification 的作用都是类与类之间的通信。但是与 delegate 不同的是:
这两个都是负责发送接收通知,剩下的事情由系统处理,所以不用返回值;而 delegate 则需要通信的对象通过变量(代理)联系;
delegate 一般是一对一,而这两个可以一对多。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风雨「83」

你的鼓励将是我创作最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值