参考学习网址: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(转)的更多相关文章

  1. iOS KVO概述

    iOS KVO概述 面试中经常会被问到:什么是KVO?这个问题既然出现概率这么大,那么我们就来详细讲一讲到底什么是KVO.下次再有面试官问你的时候,你就可以娓娓道来,以彰显高逼格 概述 问:什么是KV ...

  2. iOS:KVO/KVC 的概述与使用

    iOS:KVO/KVC 的概述与使用       KVO   APP开发技术QQ群:347072638 一,概述 KVO,即:Key-Value Observing,它提供一种机制,当指定的对象的属性 ...

  3. iOS kvo 结合 FBKVOController 的使用

    iOS kvo 结合 FBKVOController 的使用 一:FBKVOControlloer是FaceBook开源的一个 在 iOS,maxOS上使用 kvo的 开源库: 提供了block和@s ...

  4. iOS KVO详解

    一.KVO 是什么? KVO 是 Objective-C 对观察者设计模式的一种实现.[另外一种是:通知机制(notification),详情参考:iOS 趣谈设计模式——通知]: KVO 提供一种机 ...

  5. ios - kvo观察者示例

    首先创建Person分类 #import <Foundation/Foundation.h> @interface Person : NSObject @property (nonatom ...

  6. iOS KVO 学习笔记

    //// //// main.m //// TestBasis //// //// Created by ficow on 16/1/14. //// Copyright © 2016年 ficow. ...

  7. iOS - KVO 键值观察

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

  8. ios kvo

    kvo的使用方法: 1.注册: -(void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NS ...

  9. iOS KVO的原理

    KVO(Key Value Observing),是观察者模式在Foundation中的实现.   KVO的原理   简而言之就是:   1.当一个object有观察者时,动态创建这个object的类 ...

  10. 【转】 iOS KVO KVC

    原文: http://www.cocoachina.com/industry/20140224/7866.html Key Value Coding Key Value Coding是cocoa的一个 ...

随机推荐

  1. 使用jQuery快速高效制作网页交互特效---表单校验

    表单基本验证技术 为什么需要表单验证 减轻服务器的压力 保证输入的数据符合要求 常用的表单验证 1.日期格式 2.表单元素是否为空 3.用户名和密码 4.E-mail地址 5.身份证号码 表单选择器 ...

  2. PHP 创建 MySQL 表

    CREATE TABLE 语句用于创建 MySQL 表. 创建表前,我们需要使用 use myDB 来选择要操作的数据库: use myDB; 我们将创建一个名为 "MyGuests&quo ...

  3. openssl使用以及C#加密和数字签名

    如何使用openssl生成RSA公钥和私钥对 http://blog.csdn.net/scape1989/article/details/18959657 https://www.openssl ...

  4. luogu 5505 [JSOI2011]分特产 广义容斥

    共有 $m$ 种物品,每个物品 $a[i]$ 个,分给 $n$ 个人,每个人至少要拿到一件,求方案数. 令 $f[i]$ 表示钦定 $i$ 个没分到特产,其余 $(n-i)$ 个人随便选的方案数,$g ...

  5. QoS in RoCE

    QoS in RoCE 首页分类标签留言关于订阅2018-03-22 | 分类 Network  | 标签 RDMA  RoCE  ECN  PFC Overview TCP/IP协议栈满足不了现代I ...

  6. mac apache 管理

    sudo apachectl start sudo apachectl stop sudo apachectl restart

  7. Spring tools

    sts是什么? sts是spring tool suite的缩写,是基于eclipse的.开发spring应用的定制的开发环境. 提供了什么? 实现.调试.运行.部署spring应用的现成的环境.包括 ...

  8. Cesium中常用的一些地理数据文件 以及数据相关的东西

    KML Cesium.KmlDataSource.load CZML Cesium.CzmlDataSource.load GeoJson Cesium.GeoJsonDataSource.load ...

  9. arcgis python 新生成的数据设置

    try: # Update the spatial index(es) # r = arcpy.CalculateDefaultGridIndex_management(outFeatures) ar ...

  10. matlab图像灰度调整——imadjust函数的使用

    在MATLAB中,通过函数imadjust()进行图像灰度的调整,该函数调用格式如下: J=imadjust( I )  对图像I进行灰度调整 J=imadjust( I,[low_in;high_i ...