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)并不是什么新鲜事物,它来源于设计模式中的观察者模式,其基本思想就是: 一个目标对象管理所有依赖于它的观察者对象,并在它 ...
随机推荐
- 使用ThinkPHP框架高速开发站点(多图)
使用ThinkPHP框架高速搭建站点 这一周一直忙于做实验室的站点,基本功能算是完毕了.比較有收获的是大概了解了ThinkPHP框架.写一些东西留作纪念吧.假设对于相同是Web方面新手的你有一丝丝帮助 ...
- PERCONA-TOOLKIT : pt-ioprofile分析IO情况
针对IO密集型应用做系统调优的时候,我们通常都需要知道系统cpu 内存 io 网络等系统性能 和 使用率,结合应用本身的访问量,以及 mysql的性能指标来综合分析.比如说:我们将系统压力情况分为 ...
- cocos2d-x设计模式发掘之五:防御式编程模式
http://www.ityran.com/archives/2105 本文由子龙山人原创,泰然授权转载,转载请注明出处并通知子龙山人! 声明:防御式编程是提高程序代码质量的一种手段,它不能算是真正意 ...
- 认识CoreData-使用进阶
之前两篇文章都比较偏理论,文字表达比较多一些,但都是干货!学习时先理解理论知识,才能更好的帮助后面的理解. 在这篇文章中,将会涉及关于CoreData的一些复杂操作,这些操作会涉及分页查询.模糊查 ...
- Android学习之Intent传递数据
Intent在Activity中的作用主要是有两个: 1.启动目标Activity 2.传递数据 Intent在传递数据时分两种情况:向下一个Activity传递数据和从下一个Activity返回数据 ...
- uboot之at91sam9g45移植
一.第一阶段,无修改 二.第二阶段 u-boot-1.3.4\lib_arm\board.c 1.增加头文件 2.增加版本号 3.start_armboot中初始化部分 板级初始化部分init_seq ...
- 关于.NET前后台提示框的那点事
前言 关于提示框,或多或少都用到过,提示框常见方式两种:js原生alert() 和 div模拟弹层:下面以一个常见的需求业务场景来展现提示框的那点事: 正文内容 客户:需求方: 小白:实现方(全权负责 ...
- 20160405javaweb之jdbc
一.数据库驱动的概念.JDBC 数据库厂商提供的用来操作数据库用的jar包就是数据库驱动.各个厂商如果提供各自的数据库驱动的话会导致开发人员学习成本太高,所以sun公司提供了一套数据库驱动应该遵循的接 ...
- 【SQL】Update中使用表别名、如何用表中一列值替换另一列的所有值
Update中使用表别名 select中的表别名: select * from TableA as ta update中的表别名: update ta from TableA as ta 如何用表中一 ...
- 那天有个小孩跟我说LINQ(三)转载
1 LINQ TO Objects续2(代码下载) 新建项目 linq_Ch3控制台程序 1.1 操作字符串 ①查找字符串中包含的大写字母,字符串是由多个char类型组 ...