iOS-KVO(转)
参考学习网址:http://blog.sina.com.cn/s/blog_71715bf8010166ut.html
KVO就是NSKeyValueObserving的缩写,它也是Foundation Kit中的一个NSObject的Category,
KVO 基于KVC 实现,基于观察者设计模式(Observer Pattern)实现的一种通知机制,你可以
类比JAVA 中的JMS,通过订阅的方式,实现了两个对象之间的解耦,但又可以让他们相互
调用。
按照观察者模式的订阅机制,KVO 中必然有如下三个方法:
A. 订阅(Subscribe)
- (void) addObserver: (NSObject*) anObserver
forKeyPath: (NSString*) aPath
options: (NSKeyValueObservingOptions) options
context: (void*) aContext;
参数options 为NSKeyValueObservingOptionOld、NSKeyValueObservingOptionNew。
B. 取消订阅(Unsubscribe)
- (void) removeObserver: (NSObject*) anObserver
forKeyPath: (NSString*) aPath;
C. 接收通知(Receive notification)
- (void) observeValueForKeyPath: (NSString*) aPath
ofObject: (id) anObject
change: (NSDictionary*) aChange
context: (void*) aContext;
这三个方法的参数不大容易直接说清楚都是什么意思,下面我们通过实际的代码来理解。这
段代码的业务含义就是警察一直监视犯人的名字是否发生变化,只要发生变化,警察就会收
到通知。
#import <Foundation/Foundation.h>
//犯人类型
@interface Prisoner: NSObject{
int pid;
NSString *name;
}
-(void) setPid: (int) pid;
-(void) setName: (NSString*) name;
-(int) pid;
-(NSString*) name;
@end
@implementation Prisoner
-(void) setPid: (int) p{
pid=p;
}
-(void) setName: (NSString*) n{
[n retain];
[name release];
name=n;
}
-(int) pid{
return pid;
}
-(NSString*) name{
return name;
}
-(void) dealloc{
[name release];
[super dealloc];
}
@end
//警察类型
@interface Police: NSObject
@end
@implementation Police
//接收通知的方法,继承自NSObject 父类。
//请先看main 函数中的addObserver 方法参数的解释再来这个方法的解释。
//第一个参数是你监视的对象上的属性,第二个参数是你监视的对象,第三个参数存放了你
监视的属性的值,最后一个参数我们传递nil。
- (void) observeValueForKeyPath: (NSString*) aPath
ofObject: (id) anObject
change: (NSDictionary*) aChange
context: (void*) aContext{
if([aPath isEqualToString: @"name"]){
NSLog(@"Police : %@",[aChange objectForKey: @"old"]);
NSLog(@"Police : %@",[aChange objectForKey: @"new"]);
//因为main 函数中我们监听name 的新旧两个值,所以aChange 这个字典对
象里就存放了@”old”、@”new”两个key-value 对。
}
}
@end
int main (int argc , const char * argv[]){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Prisoner *prisoner=[[Prisoner alloc] init];
Police *police=[[Police alloc] init];
//为犯人添加观察者警察,警察关注犯人的name 是否发生变化,如果发生变化就立即
通知警察,也就是调用Police 中的observeValueForKeyPath 方法。
//换句话说就是警察对犯人的名字很感兴趣,他订阅了对犯人的名字变化的事件,这个
事件只要发生了,警察就会收到通知。
[prisoner addObserver: police
forKeyPath: @"name"
options: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
context: nil];
//addObserver 的调用者是要被监视的对象,第一个参数是谁要监视它,第二个参数是
监视它的哪个属性的变化(使用KVC 机制,也就是前面所说的KVO 基于KVC),第三个参
数是监视属性值改变的类型,我们这里监听Old、New,也就是Cocoa 会把name 属性改变
之前的旧值、改变之后的新值都传递到Police 的处理通知的方法,最后一个参数我们传递
nil。
//这里有一个陷阱,如果你不小心把forKeyPath 的属性名写错了,prisoner 里根本就不
存在, 那么Cocoa 不会报告任何的错误。所以当你发现你的处理通知的
observeValueForKeyPath 没有任何反应的时候,首先看一下是不是这个地方写错了。
[prisoner setName: @"豆豆"];
//警察取消订阅犯人名字变化的事件。
[prisoner removeObserver: police
forKeyPath: @"name"];
[prisoner setName: @"太狼"];
[prisoner release];
[police release];
[pool release];
return 0;
}
运行之后,Shell 窗口输出:
2011-04-01 15:20:33.467 Kvo[2004] Police : <null>//因为name 没有old 值
2011-04-01 15:09:18.479 Kvo[4004] Police : 豆豆
Notification 是Objective-C 中的另一种事件通知机制,依然以犯人、警察的示例进行演
示。
#import <Foundation/Foundation.h>
//犯人类型
@interface Prisoner: NSObject{
int pid;
NSString *name;
}
-(void) setPid: (int) pid;
-(void) setName: (NSString*) name;
-(int) pid;
-(NSString*) name;
@end
@implementation Prisoner
-(void) setPid: (int) p{
pid=p;
}
-(void) setName: (NSString*) n{
[n retain];
[name release];
name=n;
}
-(int) pid{
return pid;
}
-(NSString*) name{
return name;
}
-(void) dealloc{
[name release];
[super dealloc];
}
@end
//警察类型
@interface Police: NSObject
-(void) handleNotification:(NSNotification *) notification;
@end
@implementation Police
-(id) init{
self=[super init];
if(self){
//获取通知中心,它是单例的。
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
//向通知中心把自己添加为观察者,第一个参数是观察者,也就是警察自己,
第二个参数是观察的事件的标识符prisioner_name,这就是一个标识性的名字,不是特指哪
一个属性,第三个参数指定handleNotification 为处理通知的方法。
[nc addObserver: self selector:@selector(handleNotification:)
name:@" prisioner_name" object:nil];
}
}
//接收通知,这个方法的名字任意,只有参数是Notification 就可以了。
-(void) handleNotification:(NSNotification *) notification{
Prisoner *prisoner=[notification object];//获得通知中心传递过来的事件源对象
NSLog(@"%@",[prisoner name]);
}
@end
int main (int argc , const char * argv[]){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Prisoner *prisoner=[[Prisoner alloc] init];
Police *police=[[Police alloc] init];
[prisoner setName: @"豆豆"];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
//向通知中心发送通知,告知通知中心有一个prisioner_name 的事件发生了,并把自
己作为事件源传递给通知中心。
//通知中心随后就会查找是谁监听了prisioner_name 事件呢?找到之后就调用观察者
指定的处理方法,也就是Police 中的handleNotification 方法被调用。
[nc postNotificationName: @"prisioner_name" object: prisoner];
//从通知中心移除观察者
[nc removeObserver: police];
[prisoner setName: @"太狼"];
[prisoner release];
[police release];
[pool release];
return 0;
}
Shell 窗口输出如下所示:
2011-04-01 16:20:58.995 Notification[2564] 豆豆
我们看到这种通知方式的实现非常不优雅,观察者Police 中耦合了通知中心的API,而且最
重要的是看到红色的一行代码了吗?通知的发送是需要被监视的对象主动触发的。
iOS-KVO(转)的更多相关文章
- iOS KVO概述
iOS KVO概述 面试中经常会被问到:什么是KVO?这个问题既然出现概率这么大,那么我们就来详细讲一讲到底什么是KVO.下次再有面试官问你的时候,你就可以娓娓道来,以彰显高逼格 概述 问:什么是KV ...
- iOS:KVO/KVC 的概述与使用
iOS:KVO/KVC 的概述与使用 KVO APP开发技术QQ群:347072638 一,概述 KVO,即:Key-Value Observing,它提供一种机制,当指定的对象的属性 ...
- iOS kvo 结合 FBKVOController 的使用
iOS kvo 结合 FBKVOController 的使用 一:FBKVOControlloer是FaceBook开源的一个 在 iOS,maxOS上使用 kvo的 开源库: 提供了block和@s ...
- iOS KVO详解
一.KVO 是什么? KVO 是 Objective-C 对观察者设计模式的一种实现.[另外一种是:通知机制(notification),详情参考:iOS 趣谈设计模式——通知]: KVO 提供一种机 ...
- ios - kvo观察者示例
首先创建Person分类 #import <Foundation/Foundation.h> @interface Person : NSObject @property (nonatom ...
- iOS KVO 学习笔记
//// //// main.m //// TestBasis //// //// Created by ficow on 16/1/14. //// Copyright © 2016年 ficow. ...
- iOS - KVO 键值观察
1.KVO KVO 是 Key-Value Observing 的简写,是键值观察的意思,属于 runtime 方法.Key Value Observing 顾名思义就是一种 observer 模式用 ...
- ios kvo
kvo的使用方法: 1.注册: -(void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NS ...
- iOS KVO的原理
KVO(Key Value Observing),是观察者模式在Foundation中的实现. KVO的原理 简而言之就是: 1.当一个object有观察者时,动态创建这个object的类 ...
- 【转】 iOS KVO KVC
原文: http://www.cocoachina.com/industry/20140224/7866.html Key Value Coding Key Value Coding是cocoa的一个 ...
随机推荐
- 使用jQuery快速高效制作网页交互特效---表单校验
表单基本验证技术 为什么需要表单验证 减轻服务器的压力 保证输入的数据符合要求 常用的表单验证 1.日期格式 2.表单元素是否为空 3.用户名和密码 4.E-mail地址 5.身份证号码 表单选择器 ...
- PHP 创建 MySQL 表
CREATE TABLE 语句用于创建 MySQL 表. 创建表前,我们需要使用 use myDB 来选择要操作的数据库: use myDB; 我们将创建一个名为 "MyGuests&quo ...
- openssl使用以及C#加密和数字签名
如何使用openssl生成RSA公钥和私钥对 http://blog.csdn.net/scape1989/article/details/18959657 https://www.openssl ...
- luogu 5505 [JSOI2011]分特产 广义容斥
共有 $m$ 种物品,每个物品 $a[i]$ 个,分给 $n$ 个人,每个人至少要拿到一件,求方案数. 令 $f[i]$ 表示钦定 $i$ 个没分到特产,其余 $(n-i)$ 个人随便选的方案数,$g ...
- QoS in RoCE
QoS in RoCE 首页分类标签留言关于订阅2018-03-22 | 分类 Network | 标签 RDMA RoCE ECN PFC Overview TCP/IP协议栈满足不了现代I ...
- mac apache 管理
sudo apachectl start sudo apachectl stop sudo apachectl restart
- Spring tools
sts是什么? sts是spring tool suite的缩写,是基于eclipse的.开发spring应用的定制的开发环境. 提供了什么? 实现.调试.运行.部署spring应用的现成的环境.包括 ...
- Cesium中常用的一些地理数据文件 以及数据相关的东西
KML Cesium.KmlDataSource.load CZML Cesium.CzmlDataSource.load GeoJson Cesium.GeoJsonDataSource.load ...
- arcgis python 新生成的数据设置
try: # Update the spatial index(es) # r = arcpy.CalculateDefaultGridIndex_management(outFeatures) ar ...
- matlab图像灰度调整——imadjust函数的使用
在MATLAB中,通过函数imadjust()进行图像灰度的调整,该函数调用格式如下: J=imadjust( I ) 对图像I进行灰度调整 J=imadjust( I,[low_in;high_i ...