iOS监听模式系列之IOS中的几中观察监听模式
本文介绍Objective C中实现观察者模式(也被称为广播者/监听者、发布/注册或者通知)的五种方法以及每种方法的价值所在。
该文章将包括:
1 手动广播者和监听者(Broadcaster and listeners)
2 键-值观察(Key Value Observing)
3 通知中心(Notification center)
4 上下文通知(Context notification)
5 用于观察的委托(Delegate)
关于观察者
观察者模式是维持两个模块之间抽象关系的最强大的方式之一。观察者模式包括一个发布已发生事件的模块以及响应该事件的另一模块的若干个的实例。它和直接调 用第二个模块的方法不同,因为第一个模块不需要关注有多少个观察者,从而实现观察者和被观察者之间更加完全的抽象关系。
手动广播者和监听者
手动的方式需要广播者保有一个监听者的数组(NSArray)或集合(NSSet)。在需要通知监听者一个事件的合适时机广播者直接调用各个监听者上相关方法。
在广播者类上你可能需要一个NSMutableArray、NSSet或NSMutableDictionary。NSMutableDictionary比较适合将事件标识符的类型作为每个监听者的键值。在广播者上你还需要有监听者注册和取消注册的方法。
给NSArray或NSSet中的每个对象方式消息的方法很简单,如下:
[listenersCollection makeObjectsPerformSelector:@selector(methodSupportedByEveryListener)];
优点: 广播者对监听者列表有完全的控制。
缺点: 在集合中手动添加或移除监听者(尤其是在由于其他原因已经不被维护的情况下)。如果需要发布不同消息的情况下就需要更多的手动工作。
键值观察
键值观察协议时朝着自动化如上过程方向的一个很大进步。在很多情况下,广播者不需要做任何事情。
每个Cocoa对象自动处理用于发布任何对象的addObserver:forKeyPath:options:context:。如果广播者的 “setter”方法遵循某些规则,“setter”方法就会自动触发任何监听者的 observeValueForKeyPath:ofObject:change:context:方法。
例如如下代码就会在“source”对象上加入一个观察者::
[source addObserver:destination forKeyPath:@"myValue" options:NSKeyValueChangeNewKey context:nil];
这样在每次调用setMyValue:方法的时候都会发送一个observeValueForKeyPath:ofObject:change:context:消息到destination。
你所需要做的就是在被观察对象上注册监听者并让监听者实现observeValueForKeyPath:ofObject:change:context:。
优点: 内置的而且是自动的。可以观察任何键路径。支持依赖通知。
缺点: 广播者无法知道谁在监听。方法必须符合命名规则以实现自动观察消息的运作。监听者必须在被删除之前被移除,否者接下来的通知就会导致崩溃和失效-不过这对于该文中指出的所有方法都是一样的。
通知中心
NSNotificationCenter提供了一种更加解耦的方式。最典型的应用就是任何对象对可以发送通知到中心,同时任何对象可以监听中心的通知。
发送通知的代码如下:
[[NSNotificationCenter defaultCenter] postNotificationName:@”myNotificationName” object:broadcasterObject];
注册接收通知的代码如下:
[[NSNotificationCenter defaultCenter] addObserver:listenerObject selector:@selector(receivingMethodOnListener:) name:@”myNotificationName” object:nil];
注册通知的时候可以指定一个具体的广播者对象,但这不是必须的。你可能注意到了defaultCenter 。实际上这是你在应用中会使用到的唯一的中心。通知会向整个应用开放,因此只有一个中心。
同时还有一个NSDistributedNotificationCenter。这是用来应用间通信的。在整个计算机上只有一个该类型的中心。
优点: 通知的发送者和接受者都不需要知道对方。可以指定接收通知的具体方法。通知名可以是任何字符串。
缺点: 较键值观察需要多点代码。在删掉前必须移除监听者。
上下文通知
如果被观察属性是一个NSManagedOjbect的声明属性,就可以监听 NSManagedObjectContextObjectsDidChangeNotification。这仍然使用NSNotification方式 不过有点不同,因为NSManagedObject不会手动发送通知。
这种方法的注册如下
[[NSNotificationCenter defaultCenter] addObserver:listenerObejct selector:@selector(receivingMethodOnListener:) name:NSManagedObjectContextObjectsDidChangeNotification object:observedManagedObjectContext];
在receivingMethodOnListener:中,通知的userinfo中NSInsertedObjectsKey、NSUpdatedObjectsKey和NSDeletedObjectsKey等键值会给出受影响的对象集合。
优点: 是在整个NSManagedObjectContext中跟踪变化的最简单的方式。
缺点: 仅适用于Core Data并不能提供影响对象之外的具体信息。
用于观察的委托
最后一个Cocoa简化的观察者模式是委托。广义上说委托可以不仅仅处理简单的观察,但不一定需要做更多。
比如,NSApplication和NSWindow所有的通知都会同时传给委托并由其处理。有些类会传给它们的委托类似通知的消息,而不同时发送通知。比如NSMenu,发送menuWillOpen:给其委托但不会发送相应的NSNotification。
为了连接一个委托,只需在支持委托的对象上调用如下代码:
[object setDelegate:delegateObject];
对象可以收到任何它想要的委托消息。
优点: 支持它的类有详尽和具体信息。
缺点: 该类必须支持委托。某一时间只能有一个委托连接到某一对象。
iOS监听模式系列之IOS中的几中观察监听模式的更多相关文章
- iOS监听模式系列之iOS开发证书、秘钥
补充--iOS开发证书.秘钥 iOS开发过程中如果需要进行真机调试.发布需要注册申请很多证书,对于初学者往往迷惑不解,再加上今天的文章中会牵扯到一些特殊配置,这里就简单的对iOS开发的常用证书和秘钥等 ...
- IOS性能调优系列:使用Zombies动态分析内存中的僵尸对象
硬广:<IOS性能调优系列>第四篇,预计会有二十多篇,持续更新,欢迎关注. 前两篇<IOS性能调优系列:Analyze静态分析>.<IOS性能调优系列:使用Instrum ...
- iOS监听模式系列之通知中心
补充--通知中心 对于很多初学者往往会把iOS中的本地通知.推送通知和iOS通知中心的概念弄混.其实二者之间并没有任何关系,事实上它们都不属于一个框架,前者属于UIKit框架,后者属于Foundati ...
- iOS监听模式系列之关于delegate(代理,委托)的学习
首先,大家应该都明白的是委托是协议的一种,顾名思义,就是委托他人帮自己去做什么事.也就是当自己做什么事情不方便的时候,就可以建立一个委托,这样就可以委托他人帮自己去实现什么方法. 其次,我简单的总结了 ...
- IOS中的几中观察监听模式
本文介绍Objective C中实现观察者模式(也被称为广播者/监听者.发布/注册或者通知)的五种方法以及每种方法的价值所在. 该文章将包括: 1 手动广播者和监听者(Broadcaster and ...
- 【Xamarin挖墙脚系列:对设备/模拟器的查看调试监听】
原文:[Xamarin挖墙脚系列:对设备/模拟器的查看调试监听] 有时候我们需要查看模拟器中的文件,比如进行了文件IO操作,sqlite数据库的操作等.我们想查看内容,这时候,如何将内容导出来?由于A ...
- iOS Core Animation 简明系列教程
iOS Core Animation 简明系列教程 看到无数的CA教程,都非常的难懂,各种事务各种图层关系看的人头大.自己就想用通俗的语言翻译给大家听,尽可能准确表达,如果哪里有问题,请您指出我会尽 ...
- JavaEE开发之Spring中的事件发送与监听以及使用@Profile进行环境切换
本篇博客我们就来聊一下Spring框架中的观察者模式的应用,即事件的发送与监听机制.之前我们已经剖析过观察者模式的具体实现,以及使用Swift3.0自定义过通知机制.所以本篇博客对于事件发送与监听的底 ...
- IOS性能调优系列:使用Instruments动态分析内存泄漏
硬广:<IOS性能调优系列>第二篇,持续更新,欢迎关注. 第一篇介绍了Analyze对App做静态分析,可以发现应用中的内存泄漏问题,对于有些内存泄漏情况通过静态分析无法解决的,可以通过动 ...
随机推荐
- IMDG中的陷阱和问题
陷阱 使用cache API时,一个最重要的问题就是潜在的数据加载.因为IMDG提供的分布式集合也都是实现的JDK的Map.Set等接口,以JDK的Map为例,它接口规定put和remove返回被替换 ...
- C库源码中的移位函数
#include <stdio.h> /* _lrotr()将一个无符号长整形数左循环移位的函数 原形:unsigned long _lrotr(unsigned long value,i ...
- 15 Actionbar的显示和隐藏
ActionBar 显示隐藏方法: 在布局文件中设置 theme主题 <?xml version="1.0" encoding="utf-8"?> ...
- springMVC系列之(三) spring+springMVC集成(annotation方式)
个人认为使用框架并不是很难,关键要理解其思想,这对于我们提高编程水平很有帮助.不过,如果用都不会,谈思想就变成纸上谈兵了!!!先技术,再思想.实践出真知. 1.基本概念 1.1.Spring Spri ...
- linux真正使用shell脚本做定时任务 关键的Nohup
网上有很多的文章教大家使用定时任务,所以别的废话我就不多说了 我这里直接有SH来做定时,只是有一点大家不知道,一定要用Nohup,否则用户退出终端以后,SH任务会被自动终止掉 假设有一 tash.sh ...
- SpringMVC系列之(一) 入门实例
Spring MVC是非常优秀的MVC框架,由其是在3.0版本发布后,现在有越来越多的团队选择了Spring3 MVC了.Spring MVC结构简单,应了那句话简单就是美,而且他强大不失灵活,性能也 ...
- Spring+Hibernate4 Junit 报错No Session found for current thread
论坛上有另外一篇更全面的帖子,jinnianshilongnian写的:http://www.iteye.com/topic/1120924 本文的环境是: spring-framework-3.1 ...
- Android学习之Animation(二)
接着上次的View Animation动画,这次是Frame Animation.具体点来讲就是在Frame层面上进行变化的动画效果的设置.说白了就是定时更换"背景"图.来实现不同 ...
- B2B、B2C、B2D的简单理解
B2D现在非常流行,顾名思义,B2D 就是指那些以开发者为对象的服务,它们通过 API 等形式"售卖"自己某一方面的特长.B2D(Business to Developer)市场很 ...
- Java中函数的递归调用
说到递归,java中的递归和C语言中也是很相似的,在Java中,递归其实就是利用了栈的先进后出的机制来描述的. public class HelloWorld { public static void ...