KVO - 键值观察
【基本概念】
键值观察是一种使对象获取其他对象的特定属性变化的通知机制。控制器层的绑定技术就是严重依赖键值观察获得模型层和控制器层的变化通知的。对于不依赖控制器层类的应用程序,键值观察提供了一种简化的方法来实现检查器并更新用户界面值。
与NSNotification不同,键值观察并没有所谓的中心对象来为所有观察者提供变化通知。取而代之的,当有变化发生时,通知被直接发送至处于观察状态的对象。NSObject提供这种基础的键值观察实现方法,你几乎不用重写该方法。
你可以观察任意对象属性,包括简单属性,对一或是对多关系。对多关系的观察者将会被告知发生变化的类型-也就是任意发生变化的对象。键值观察为所有对象提供自动观察兼容性。你可以通过禁用自动观察通知并实现手动通知来筛选通知。
【注册观察者】
为了正确接收属性的变更通知,观察者必须首先发送一个addObserver:forKeyPath:options:context:消息至被观察对象,用以传送观察对象和需要观察的属性的关键路径,以便与其注册。选项参数指定了发送变更通知时提供给观察者的信息。使用NSKeyValueObservingOptionOld选项可以将初始对象值以变更字典中的一个项的形式提供给观察者。指定NSKeyValueObservingOptionNew选项可以将新的值以一个项的形式添加至变更字典。你可以使用逐位“|”这两个常量来指定接受上述两种类型的值。
下面我通过几个实例来带大家实现一下KVO的通知机制:
【实例一】对基本数据类型的属性进行观察
(1)我建立的是一个基于OC的iOS项目,在storyboard中拖入一个按钮,并在ViewController中使用IBAction实现按钮点击。
(2)声明一个int类型的属性在ViewController.m文件中:
- @interface ViewController ()
- @property(assign,nonatomic) int count;
- @end
(3)然后实现一个初始化方法,初始化count的值:
- - (instancetype)init
- {
- self = [super init];
- if (self) {
- self.count = 1;
- }
- return self;
- }
(4)在按钮点击响应中进行自加运算,以后我就监听点击按钮count数值改变的这个事件:
- - (IBAction)clicked:(id)sender {
- self.count++;
- }
(5)在viewDidLoad方法中注册观察事件:
- - (void)viewDidLoad {
- [super viewDidLoad];
- [self addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
- }
(6)最后重写一个方法observeValueForKeyPath;如下:
- - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(voidvoid *)context{
- if ([keyPath isEqual: @"count"]) {
- NSLog(@"count = %d",self.count);
- }
- }
(7)输出结果如下:每当我点击按钮,观察事件就会调用注册的方法。
。
【实例二】对 对象进行观察
(1)在上述的基础上,新建一个Other类,在h头文件中声明一个变量:
- #import <Foundation/Foundation.h>
- @interface Other : NSObject
- @property(assign,nonatomic) int number;
- @end
(2)在Other.m文件中实现初始化方法,初始化number变量:
- #import "Other.h"
- @implementation Other
- - (instancetype)init
- {
- self = [super init];
- if (self) {
- self.number = 100;
- }
- return self;
- }
- @end
(3)在ViewController.m中实现如下:
- #import "ViewController.h"
- #import "Other.h"
- @interface ViewController ()
- @property(strong,nonatomic) Other *other;
- @end
- @implementation ViewController
- - (void)viewDidLoad {
- [super viewDidLoad];
- //监听Other类;
- self.other = [[Other alloc] init];
- [self.other addObserver:self forKeyPath:@"number" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
- }
- - (IBAction)clicked:(id)sender {
- _other.number++;
- }
- - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(voidvoid *)context{
- //我假设能被2整除时输出,注意我使用的是keyPath进行匹配;
- if ([keyPath isEqual: @"number"] && _other.number % 2 == 0){
- NSLog(@"other.number = %d",_other.number);
- }
- }
- @end
(4)输出结果如下:
。
【实例三】同时对多个对象进行观察
在上述【实例一】【实例二】的基础上,我同时对两个变量进行观察,其他类中的实现不变,ViewController.m中的实现如下:
- #import "ViewController.h"
- #import "Other.h"
- @interface ViewController ()
- @property(assign,nonatomic) int count;
- @property(strong,nonatomic) Other *other;
- @end
- @implementation ViewController
- - (void)viewDidLoad {
- [super viewDidLoad];
- [self addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
- //监听Other类;
- self.other = [[Other alloc] init];
- [self.other addObserver:self forKeyPath:@"number" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
- }
- - (instancetype)init
- {
- self = [super init];
- if (self) {
- self.count = 1;
- }
- return self;
- }
- - (IBAction)clicked:(id)sender {
- _other.number++;
- self.count++;
- }
- - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(voidvoid *)context{
- if (object == self.other) {
- NSLog(@"number = %d",_other.number);
- }
- else if (object == self && self.count % 2 == 0){
- NSLog(@"count = %d",self.count);
- }
- }
- @end
输出结果如下:
。
【实例四】使用change参数实时观察参数变化
ViewController.m中的实现如下:
- #import "ViewController.h"
- #import "Other.h"
- @interface ViewController ()
- @property(assign,nonatomic) int count;
- @property(strong,nonatomic) Other *other;
- @end
- @implementation ViewController
- - (void)viewDidLoad {
- [super viewDidLoad];
- [self addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
- }
- - (instancetype)init
- {
- self = [super init];
- if (self) {
- self.count = 1;
- }
- return self;
- }
- - (IBAction)clicked:(id)sender {
- _other.number++;
- self.count++;
- }
- - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(voidvoid *)context{
- //在这里对观察变量进行打印;
- NSLog(@"%@",change);
- }
- @end
输出结果如下:
KVO - 键值观察的更多相关文章
- K-V-O 键值观察机制
在两个不同的控制器之间传值是iOS开发中常有的情况,应对这种情况呢,有多种的应对办法.kvc就是其中的一种,所以,我们就在此解释之. key value observing 键值观察,给人一种高 ...
- iOS - KVO 键值观察
1.KVO KVO 是 Key-Value Observing 的简写,是键值观察的意思,属于 runtime 方法.Key Value Observing 顾名思义就是一种 observer 模式用 ...
- KVO(键-值观察)
// 1.键-值观察 // 2.它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知. // 3.符合KVC(Key-ValuedCoding)机制的对象才可以使用KVO // 4.实现过 ...
- KVO键值观察的具体实现
1.KVO简介 KVO是Objective-C对观察者设计模式的一种实现,它提供一种机制,指定一个被观察对象(如A类),当对象中的某个属性发生变化的时候,对象就会接收到通知,并作出相应的处理.在MVC ...
- OC键值观察KVO
什么是KVO? 什么是KVO?KVO是Key-Value Observing的简称,翻译成中文就是键值观察.这是iOS支持的一种机制,用来做什么呢?我们在开发应用时经常需要进行通信,比如一个model ...
- 路径(keyPath)、键值编码(KVC)和键值观察(KVO)
键路径 在一个给定的实体中,同一个属性的所有值具有相同的数据类型. 键-值编码技术用于进行这样的查找—它是一种间接访问对象属性的机制. - 键路径是一个由用点作分隔符的键组成的字符串,用于指定一个连接 ...
- 09 (OC)* 键路径(keyPath)、键值编码(KVC)、键值观察(KVO)
键路径在一个给定的实体中,同一个属性的所有值具有相同的数据类型.键-值编码技术用于进行这样的查找—它是一种间接访问对象属性的机制. - 键路径是一个由用点作分隔符的键组成的字符串,用于指定一个连接在一 ...
- 深度理解Key-Value Observing 键值观察
前言 在上一阶段的开发过程中,我们大量使用了 KVO 机制,来确保页面信息的及时同步.也因此碰到了很多问题,促使我们去进一步学习 KVO 的相关机制,再到寻找更好的解决方案.鉴于 KVO 让人欲仙 ...
- [深入浅出Cocoa]详解键值观察(KVO)及其实现机理
一,前言 Objective-C 中的键(key)-值(value)观察(KVO)并不是什么新鲜事物,它来源于设计模式中的观察者模式,其基本思想就是: 一个目标对象管理所有依赖于它的观察者对象,并在它 ...
随机推荐
- 导入cocos2d-x samples android官方示例
导了一晚上samples android示例,查了一晚上资料,费了很大的劲,终于成功导入并运行成功,分享一下经验: 1.下载eclipse与ADT跟android SDK,相信大家都会装了吧. 2.下 ...
- mysql导出部分(指定)数据库表字段
需要导出某个表中的部分字段信息 之前导出数据库表一直使用mysqldump命令,例如: mysqldump -hIP -uroot -P3306 -p 库 表 > 名字.sql 但是如果导出 ...
- Top 10 Questions about Java Exceptions--reference
reference from:http://www.programcreek.com/2013/10/top-10-questions-about-java-exceptions/ This arti ...
- Flash学习初总结
话说尝试了一周多的Flash编程,有些理解为什么很多程序员都不喜欢用Flash编程了. 首先,就是没有编程的难度,想要编好Flash,也就是有良好的视觉效果,那么关键点不在你的程序逻辑或者代码条理上, ...
- Linux 释放cached内存
使用free -m 查看系统使用的内存情况: # free -m total used free shared buffers ...
- last_9t's_ramsey
cannot finish his face
- 面向对象(POP)和面向过程(OOP)
我对面向对象和面向过程的理解 面向过程:(procedure oriented programming 即:POP) 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时 ...
- 关于FPGA异步时钟采样--结绳法的点点滴滴
一.典型方法 典型方法即双锁存器法,第一个锁存器可能出现亚稳态,但是第二个锁存器出现亚稳态的几率已经降到非常小,双锁存器虽然不能完全根除亚稳态的出现(事实上所有电路都无法根除,只能尽可能降低亚稳态的出 ...
- gdal和python在windows上的安装
GDAL is a useful command line tool to process spatial data, if you haven’t heard of the tool before ...
- JavaScript如何获得Select下拉框选中的值
js代码: var mySelect = document.getElementById("resultList2"); var mySelectText = mySelect.o ...