iOS ---观察者模式

观察者模式本质上时一种发布-订阅模型,用以消除具有不同行为的对象之间的耦合,通过这一模式,不同对象可以协同工作,同时它们也可以被复用于其他地方Observer从Subject订阅通知,ConcreteObserver实现重现ObServer并将其重载其update方法。一旦SubJect的实例需要通知Observer任何新的变更,Subject会发送update消息来通知存储在其内部类中所注册的Observer、在ConcreteObserver的update方法的实际实现中,Subject的内部状态可被取得并进行后续处理。其类图如下:

观察者模式.png

由上面我们可以发现观察者模式无非在是定义对象间的一种一对多的依赖关系,并且当一个对象的状态发生改变的时候,所有依赖于它的对象都会得到通知且自动更新。即如果Subject允许其他观察者(实现了观察者接口的对象)对这个Subject的改变进行请阅,当Subject发送了变化,那么Subject会将这个变化发送给所有的观察者,观察者就能对Subject的变化做出更新。其时序图如下

观察者模式2.png

通过上面的观察我们可以发现如果用N个Observer来拓展Subject的行为,这些Observer具有处理存储在Subject中的信息的特定实现,这样也就实现了前面所说的消除不同对象间的耦合的功能了。
那么了解了这些我们可能就会更像了解下我们在什么时候才会去使用观察者模式呢?

  • 当需要将改变通知所有的对象时,而你又不知道这些对象的具体类型
  • 改变发生在同一个对象中,并需要改变其他对象将相关的状态进行更新且不知道有多少个对象。

而同样的在我们日常的开发中在Cocoa Touch框架中的的两种经常打交道的技术KVO与通知都实现了观察者模式,所以下面我们讨论的重点也就是基于这两个方面的。

通知

小编发布了一篇文章,地址是:http://www.jianshu.com/p/2efc71c4188a 里面有通知的基础用法,这里就不过多的介绍了。

KVO

KVO是Key-Value-Observing的缩写

通过KVO这种机制对象可以通过它得到其他对象的某个属性的变更通知。这种机制在MVC模式下显得更为重要,KVO可以让视图对象经过控制器观察模型对象的变更从而做出更新等操作。
KVO这一机制是基于NSKeyValueObserving协议的,Cocoa通过这个协议为所有遵循协议的对象提供了自动观察属性变化的能力。在NSObject中已经为我们实现了这一协议,所以我们不必去实现这个协议。
下图形象的表示了KVO的一种工作流程:


Screen Shot 2014-06-15 at 3.31.32 PM

为什么要使用KVO?

有的朋友可能会有疑问,为什么要使用KVO呢?KVO能实现的我使用Setter方法同样能实现啊。其实不然KVO存在还是有它的价值的,那么接下来我们细数一下KVO的独特价值吧:
1.我们创建一两个setter方法感觉没什么,但是如果要观察的属性非常多,那么还能一一重写setter方法来实现吗?想必大家心里已有了答案,但是利用KVO则能很好的解决上述问题。
2.我们自定义的类是很容易改写setter方法的,但是如果你是用一个已经编译好了的类库时要监控其中一个属性时怎么办?难道还要去重写setter方法?如果使用KVO则很轻松解决问题。
3.使用KVO能够方便的记录变化前的值和变化后的值,不适用KVO你还要自己来解决这些问题。
4.KVO让你的代码看起来更加简洁清晰易于维护。

观察的是,属性是否执行了setter方法或者是是否使用了kvc赋值了,只要有赋值的动作,都会执行kvo的回调方法。如果赋值没有通过setter方法或者KVC,例如(_name = @"新值"),这个时候,不会触发kvo回调方法

一般KVO崩溃的原因

1.被观察的对象销毁掉了(被观察的对象是一个局部变量)2.观察者被释放掉了,但是没有移除监听 3.注册的监听没有移除掉,又从新注册了一遍监听

KVO使用方法

添加观察者和被观察者

    //你要观察那个对象,就给那个对象添加一个观察者
//观察的是self.view 的backgroundColor属性 获取旧值和新值
    //observer:观察者(观察self.view对象属性的变化)
    //keypath:被观察属性的名称
    //观察属性的新值,旧值等的一些配置(枚举值)
    //content:上下文,可以为kvo的回调方法传值
    //注册观察者(添加观察者)
    [self.view addObserver:self forKeyPath:@"backgroundColor" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil]; 

//观察Person类的对象的name属性
[self.person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];

KVO回调方法

//keyPath:属性名称
//object:被观察的对象
//change:变化前后的值都存储在Change字典中
//context:注册观察者的时候content传递过来的值。
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    //监听了好几个属性,使用keyPath区分
    //监听了好几个view,通过object判断
    
    //view的背景颜色发生了变化
    if ([keyPath isEqualToString:@"backgroundColor"]) {
        id oldColor = [change objectForKey:NSKeyValueChangeOldKey];
        NSLog(@"旧值---%@---%@", NSKeyValueChangeOldKey, oldColor);
        id newColor = [change objectForKey:NSKeyValueChangeOldKey];
        NSLog(@"新值---%@---%@", NSKeyValueChangeNewKey, newColor);
    }
   //name属性发生变化
    if ([keyPath isEqualToString:@"name"]) {
        id oldName = [change objectForKey:@"old"];
        NSLog(@"oldName == %@", oldName);
        
        id newName = [change objectForKey:@"new"];
        NSLog(@"newName == %@", newName);
    }
}

最后使用完之后释放掉观察者 一般在dealloc 或者是viewDidDisappear:方法中释放掉观察者

//在视图已经消失,移除监听
- (void)viewDidDisappear:(BOOL)animated {
    //移除监听
    [self.view removeObserver:self forKeyPath:@"name" context:nil];
}
//在ARC下,不能使用[super delloc]
- (void)dealloc {
    //移除监听
    [self.person removeObserver:self forKeyPath:@"name" context:nil];
    self.person = nil;
}

参考文章:http://blog.csdn.net/xdrt81y/article/details/24039163 作者:LoveApp_Han

http://www.jianshu.com/p/56d9417c3a04 作者:晓风沐晨 http://www.jianshu.com/users/350fee9655f0/latest_articles

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 1 场景问题# 1.1 订阅报纸的过程## 来考虑实际生活中订阅报纸的过程,这里简单总结了一下,订阅报纸的基本流程...
    七寸知架构阅读 4,569评论 5 57
  • 什么是观察者模式?当A对B的变化感兴趣,需要监听B的状态变化,就注册为B的观察者,当B发生变化时通知A,告知B发生...
    _Lily阅读 1,570评论 2 4
  • 一.什么是观察者模式? 简单的说就是一个对象拥有多个特征,当某一个特征发生变化时,另外一个对象做出相应的处理和操作...
    LYSNote阅读 4,196评论 0 5
  • KVO即:Key-Value Observing, 直译为:基于键值的观察者。 它提供一种机制,当指定的对象的属性...
    _Lily阅读 1,008评论 0 1
  • //联系人:石虎QQ:1224614774昵称:嗡嘛呢叭咪哄 一、观察者模式优点: 1.观察者模式在被观察者和观察...
    石虎132阅读 3,256评论 0 4