【基本概念】

键值观察是一种使对象获取其他对象的特定属性变化的通知机制。控制器层的绑定技术就是严重依赖键值观察获得模型层和控制器层的变化通知的。对于不依赖控制器层类的应用程序,键值观察提供了一种简化的方法来实现检查器并更新用户界面值。

与NSNotification不同,键值观察并没有所谓的中心对象来为所有观察者提供变化通知。取而代之的,当有变化发生时,通知被直接发送至处于观察状态的对象。NSObject提供这种基础的键值观察实现方法,你几乎不用重写该方法。

你可以观察任意对象属性,包括简单属性,对一或是对多关系。对多关系的观察者将会被告知发生变化的类型-也就是任意发生变化的对象。键值观察为所有对象提供自动观察兼容性。你可以通过禁用自动观察通知并实现手动通知来筛选通知。

【注册观察者】

为了正确接收属性的变更通知,观察者必须首先发送一个addObserver:forKeyPath:options:context:消息至被观察对象,用以传送观察对象和需要观察的属性的关键路径,以便与其注册。选项参数指定了发送变更通知时提供给观察者的信息。使用NSKeyValueObservingOptionOld选项可以将初始对象值以变更字典中的一个项的形式提供给观察者。指定NSKeyValueObservingOptionNew选项可以将新的值以一个项的形式添加至变更字典。你可以使用逐位“|”这两个常量来指定接受上述两种类型的值。

下面我通过几个实例来带大家实现一下KVO的通知机制:

【实例一】对基本数据类型的属性进行观察

(1)我建立的是一个基于OC的iOS项目,在storyboard中拖入一个按钮,并在ViewController中使用IBAction实现按钮点击。

(2)声明一个int类型的属性在ViewController.m文件中:

    1. @interface ViewController ()
    2. @property(assign,nonatomic) int count;
    3. @end

(3)然后实现一个初始化方法,初始化count的值:

    1. - (instancetype)init
    2. {
    3. self = [super init];
    4. if (self) {
    5. self.count = 1;
    6. }
    7. return self;
    8. }

(4)在按钮点击响应中进行自加运算,以后我就监听点击按钮count数值改变的这个事件:

    1. - (IBAction)clicked:(id)sender {
    2. self.count++;
    3. }

(5)在viewDidLoad方法中注册观察事件:

    1. - (void)viewDidLoad {
    2. [super viewDidLoad];
    3. [self addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
    4. }

(6)最后重写一个方法observeValueForKeyPath;如下:

    1. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(voidvoid *)context{
    2. if ([keyPath  isEqual: @"count"]) {
    3. NSLog(@"count = %d",self.count);
    4. }
    5. }

(7)输出结果如下:每当我点击按钮,观察事件就会调用注册的方法。

【实例二】对 对象进行观察

(1)在上述的基础上,新建一个Other类,在h头文件中声明一个变量:

  1. #import <Foundation/Foundation.h>
  2. @interface Other : NSObject
  3. @property(assign,nonatomic) int number;
  4. @end

(2)在Other.m文件中实现初始化方法,初始化number变量:

  1. #import "Other.h"
  2. @implementation Other
  3. - (instancetype)init
  4. {
  5. self = [super init];
  6. if (self) {
  7. self.number = 100;
  8. }
  9. return self;
  10. }
  11. @end

(3)在ViewController.m中实现如下:

  1. #import "ViewController.h"
  2. #import "Other.h"
  3. @interface ViewController ()
  4. @property(strong,nonatomic) Other *other;
  5. @end
  6. @implementation ViewController
  7. - (void)viewDidLoad {
  8. [super viewDidLoad];
  9. //监听Other类;
  10. self.other = [[Other alloc] init];
  11. [self.other addObserver:self forKeyPath:@"number" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
  12. }
  13. - (IBAction)clicked:(id)sender {
  14. _other.number++;
  15. }
  16. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(voidvoid *)context{
  17. //我假设能被2整除时输出,注意我使用的是keyPath进行匹配;
  18. if ([keyPath  isEqual: @"number"] && _other.number % 2 == 0){
  19. NSLog(@"other.number = %d",_other.number);
  20. }
  21. }
  22. @end

(4)输出结果如下:

【实例三】同时对多个对象进行观察

在上述【实例一】【实例二】的基础上,我同时对两个变量进行观察,其他类中的实现不变,ViewController.m中的实现如下:

  1. #import "ViewController.h"
  2. #import "Other.h"
  3. @interface ViewController ()
  4. @property(assign,nonatomic) int count;
  5. @property(strong,nonatomic) Other *other;
  6. @end
  7. @implementation ViewController
  8. - (void)viewDidLoad {
  9. [super viewDidLoad];
  10. [self addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
  11. //监听Other类;
  12. self.other = [[Other alloc] init];
  13. [self.other addObserver:self forKeyPath:@"number" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
  14. }
  15. - (instancetype)init
  16. {
  17. self = [super init];
  18. if (self) {
  19. self.count = 1;
  20. }
  21. return self;
  22. }
  23. - (IBAction)clicked:(id)sender {
  24. _other.number++;
  25. self.count++;
  26. }
  27. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(voidvoid *)context{
  28. if (object == self.other) {
  29. NSLog(@"number = %d",_other.number);
  30. }
  31. else if (object == self && self.count % 2 == 0){
  32. NSLog(@"count = %d",self.count);
  33. }
  34. }
  35. @end

输出结果如下:

【实例四】使用change参数实时观察参数变化

ViewController.m中的实现如下:

  1. #import "ViewController.h"
  2. #import "Other.h"
  3. @interface ViewController ()
  4. @property(assign,nonatomic) int count;
  5. @property(strong,nonatomic) Other *other;
  6. @end
  7. @implementation ViewController
  8. - (void)viewDidLoad {
  9. [super viewDidLoad];
  10. [self addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
  11. }
  12. - (instancetype)init
  13. {
  14. self = [super init];
  15. if (self) {
  16. self.count = 1;
  17. }
  18. return self;
  19. }
  20. - (IBAction)clicked:(id)sender {
  21. _other.number++;
  22. self.count++;
  23. }
  24. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(voidvoid *)context{
  25. //在这里对观察变量进行打印;
  26. NSLog(@"%@",change);
  27. }
  28. @end

输出结果如下:

KVO - 键值观察的更多相关文章

  1. K-V-O 键值观察机制

    在两个不同的控制器之间传值是iOS开发中常有的情况,应对这种情况呢,有多种的应对办法.kvc就是其中的一种,所以,我们就在此解释之.   key value observing  键值观察,给人一种高 ...

  2. iOS - KVO 键值观察

    1.KVO KVO 是 Key-Value Observing 的简写,是键值观察的意思,属于 runtime 方法.Key Value Observing 顾名思义就是一种 observer 模式用 ...

  3. KVO(键-值观察)

    // 1.键-值观察 // 2.它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知. // 3.符合KVC(Key-ValuedCoding)机制的对象才可以使用KVO // 4.实现过 ...

  4. KVO键值观察的具体实现

    1.KVO简介 KVO是Objective-C对观察者设计模式的一种实现,它提供一种机制,指定一个被观察对象(如A类),当对象中的某个属性发生变化的时候,对象就会接收到通知,并作出相应的处理.在MVC ...

  5. OC键值观察KVO

    什么是KVO? 什么是KVO?KVO是Key-Value Observing的简称,翻译成中文就是键值观察.这是iOS支持的一种机制,用来做什么呢?我们在开发应用时经常需要进行通信,比如一个model ...

  6. 路径(keyPath)、键值编码(KVC)和键值观察(KVO)

    键路径 在一个给定的实体中,同一个属性的所有值具有相同的数据类型. 键-值编码技术用于进行这样的查找—它是一种间接访问对象属性的机制. - 键路径是一个由用点作分隔符的键组成的字符串,用于指定一个连接 ...

  7. 09 (OC)* 键路径(keyPath)、键值编码(KVC)、键值观察(KVO)

    键路径在一个给定的实体中,同一个属性的所有值具有相同的数据类型.键-值编码技术用于进行这样的查找—它是一种间接访问对象属性的机制. - 键路径是一个由用点作分隔符的键组成的字符串,用于指定一个连接在一 ...

  8. 深度理解Key-Value Observing 键值观察

    前言   在上一阶段的开发过程中,我们大量使用了 KVO 机制,来确保页面信息的及时同步.也因此碰到了很多问题,促使我们去进一步学习 KVO 的相关机制,再到寻找更好的解决方案.鉴于 KVO 让人欲仙 ...

  9. [深入浅出Cocoa]详解键值观察(KVO)及其实现机理

    一,前言 Objective-C 中的键(key)-值(value)观察(KVO)并不是什么新鲜事物,它来源于设计模式中的观察者模式,其基本思想就是: 一个目标对象管理所有依赖于它的观察者对象,并在它 ...

随机推荐

  1. careercup-数学与概率 7.6

    7.6 在二维平面上,有一些点,请找出经过点数最多的那条线. 解法: 类似于leetcode:Max Points on a Line 我们只需在任意两点之间“画”一条无限长的直线(也即不是线段),并 ...

  2. hdu1002大数相加

    A + B Problem II Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tot ...

  3. android开发之使用上下文菜单

    android中的上下文菜单类似于PC上的鼠标右键单击,不同的是android上没有鼠标这一概念,更谈不上右键单击,在android中,一般是长按某个View,调出上下文菜单.与OptionsMenu ...

  4. WPF 自定义路由事件 与 附加路由事件

    为student添加附件事件

  5. 【转】ArrayList的toArray

    [转]ArrayList的toArray ArrayList提供了一个将List转为数组的一个非常方便的方法toArray.toArray有两个重载的方法: 1.list.toArray(); 2.l ...

  6. java中substring和indexof() 和lastindexof()

    java中substring和indexof() 和lastindexof() str=str.substring(int beginIndex);截取掉str从首字母起长度为beginIndex的字 ...

  7. java 用eclipse j2ee写的servlet 程序,WEB-INF下的配置文件web.xml在哪啊?谢谢!

    我用的版本是tomcat7.0,在webcontent\web-inf里只有一个空文件夹lib,写完servlet 类程序,就可以运行了,我想知道自动生成的配置文件在哪里?或者说从哪里能够看出来配置内 ...

  8. 如何在已安装vs2010的基础上安装sql2008

    以前老受到别人写的这类东西的帮助,所以这次决定自己试下,第一次发这种,写得不好莫怪.       涉略sql2008一个多星期了.怎么说呢?Transact-SQL的编程虽然不如C++,java等高级 ...

  9. 如何搭建javaweb 开发环境

    一.准备工作: (1) 环境要求: 1.java jdk 2.eclipse--j2ee版 3.tomcat 4.mysql 5.HeidiSQL_7.0 (2)搭建步骤: 1.安装JDK,配置环境变 ...

  10. 20160417javaweb之servlet监听器

    监听器:监听器就是一个java程序,功能是监听另一个java对象变化(方法调用.属性变更) 8个监听器,分为了3种 写一个类实现响应的接口 注册监听器 -- 在web.xml中注册监听器 1.用来监听 ...