iOS 趣谈设计模式——通知
【前言介绍】
iOS的一种设计模式,观察者Observer模式(也叫发布/订阅,即Publich/Subscribe模式)。
观察者模式,包含了通知机制(notification)和KVO(Key-value-observing)机制。
在这本文中,我们将介绍在日常项目当中经常使用到的通知机制这一种设计模式。
通知机制
委托机制是代理“一对一”的对象之间的通信,而通知机制是广播“一对多”的对象之间的通信;
一、是什么?【生活问题例子】
“短信天气预报”
当A类发送一条信息给通知中心时,注册为用户(观察者)的B类群就会收到相应的通知,并作出反应。
二、有什么用?【代码中的应用】
在不同类之间如何传递数据?
有几种方法:属性传递、代理协议,另外就是通知。
通知:在A类中创建的方法,B类中执行,且可以使用该通知携带数据传递给对方;
三、有什么不同?【与其他“通知”的不同?】
经常提到的通知,有“广播通知”、“本地通知”、“推送通知”
本文所介绍的就是广播通知,是实现观察者模式的一种机制,可以在一个应用中的多个对象之间进行通信传递数据。
而本地通知和推送通知主要是给用户发送“通知提示”,例如警告提示、声音、震动以及如图标上的红色数字提示。
第一种由“本地发送通知”给用户,第二种由第三方应用发送给苹果官方的远程服务器,然后再由服务器“推送通知”给用户。
四、产品经理:老规矩,代码拿来~【具体实现】
过程:
- 在通知机制中,需要(或者说感兴趣)接收某个通知的信息的所有对象都可以成为接收者,首先注册成为观察者。
- 进行注册后,通知中心就会把发布者发送的通知信息,广播给注册过该通知的观察者。且观察者只能接收到通知中心的信息,不能知道通知是谁投送的。
- 最后,接受者不想再对关注该通知的信息时,可以给通知中心发生解除注册的信息,之后都不再接收到通知了。
1.获取通知中心(NSNotificationCenter)对象:(就像获取移动营运商短信中心的权限,作为媒介)
发布、注册、解除通知都需要使用通知中心,负责协助不同对象、不同类之间的消息通信。
[NSNotificationCenter defaultCenter]; //需要注意的是,通知中心也是一个单例
2.发布(A类)和接收(B类)
a.做为发布者的A类发送通知:
可以使用一下三个方法:
- (void)postNotification:(NSNotification *)notification; - (void)postNotificationName:(NSString *)aName object:(id)anObject; - (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
- postNotificationName:指定消息名称;
- object:指定发消息者;
- userInfo:通知中用于传递参数的载体,传递的方法是把参数放在NSDictionary类型的userInfo中。例如:NSDictionary *dict = [notification userInfo];
一般使用第三个方法,如果参数不需要的,可以设置为nil.
b.注册通知,加入观察者:
做为观察者B类注册通知,进行监听:
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSString *)aName object:(nullable id)anObject;
//@selector中为回调方法,在本类中对通知进行相应的处理,name为通知名称、object为对象;
剖析:
- object == nil,那么客户对象(self)将收到任何对象发出NSWindowDidBecomeMainNotification的通知消息;
- name == nil,那么观察者将接收到object对象的所有消息,但是确定不了接收这些消息的顺序。
- object == nil,name == nil,那么该观察者将收到所有对象的所有消息。
对于一个任意的观察者observer,如果不能保证其对应的selector有本类自定义的方法(例如:MyMethod),可采用[observer respondsToSelector:@selector(MyMethod:)]] 进行检查。
所以完整的添加观察者过程为:
if([observer respondsToSelector:@selector(MyMethod:)]) {
[[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(MyMethod:) name:NSWindowDidBecomeMainNotification object:nil];
}
当然在苹果API中也有另外一个注册观察者的方法:
- (id <NSObject>)addObserverForName:(nullable NSString *)name object:(nullable id)obj queue:(nullable NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block
此方法是支持在该方法中进行block回调的,而queue参数就是表示此模块在queue队列中进行。
但是这方法一般不采用,因为在此方法的 block 中,稍微不注意调用 self 的话,会引起循环引用,造成内存泄露,所以还是建议使用第一种方法进行观察者的创建。
c.移除通知
注册过的对象必须在释放之前注销掉,如果不这样的话,当该通知再次出现时,通知中心可能会向已释放的观察者对象发送消息,从而导致应用崩溃。
在ARC下,系统会自动回收无用的通知对象内存,但是由于系统回收机制ARC有一定的延迟性,所以即使不会出错,也建议养成习惯,对通知进行手动释放无用的通知。
移除有2种方法:
//释放所有通知
- (void)removeObserver:(id)observer;
//释放名称为aName的通知
- (void)removeObserver:(id)observer name:(nullable NSString *)aName object:(nullable id)anObject;
一般在视图控制器中,可以在“didReceiveMemoryWarning:”中发送解除消息:【这只是参考,建议还是在 :-(void)dealloc ){} 中进行移除。 】
-(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
//移除观察者
[[NSNotificationCenter defaultCenter]removeObserver:self];
}
(by:从 iOS 9 开始通知中心会对观察者进行 weak 弱引用,所以不需要在观察者对象释放之前从通知中心移除。即使不对通知进行手动移除,指针也会在注册者被回收后自动置空,向空指针 nil 发送消息是不会有问题的。
但是,通过 - (id )addObserverForName: object: queue: usingBlock:
方法注册的观察者依然需要手动的释放,因为通知中心对它们持有的是强引用。)
五、那些年我们用过的系统通知名称~
系统自带的也有许多有用的通知,我们只需要注册为相应的通知接收对象,就能根据通知状态的变化发生相应的数据改变。
部分系统通知名称如下:
UIApplicationDidFinishLaunchingNotification // 应用程序启动后
UIApplicationDidBecomActiveNotification // 进入前台
UIApplicationWillResignActiveNotification // 应用将要进入后台
UIApplicationDidEnterBackgroundNotification // 进入后台
UIKeyboardWillShowNotification // 键盘即将显示
UIKeyboardDidShowNotification // 键盘显示完毕
UIKeyboardWillHideNotification // 键盘即将隐藏
UIKeyboardDidHideNotification // 键盘隐藏完毕
六、举个栗子:“
iOS 趣谈设计模式——通知的更多相关文章
- IOS开发常用设计模式
IOS开发常用设计模式 说起设计模式,感觉自己把握不了笔头,所以单拿出iOS开发中的几种常用设计模式谈一下. 单例模式(Singleton) 概念:整个应用或系统只能有该类的一个实例 在iOS开发我们 ...
- [转]ASP.NET应用程序生命周期趣谈(五) IIS7瞎说
Ps:建议初学者在阅读本文之前,先简要了解一下之前的几篇文章,以便于熟悉本文提到的一些关于IIS6的内容,方便理解.仅供参考. PS:为什么叫瞎说呢?我觉得自己理解的并不到位,只能是作为一个传声筒,希 ...
- iOS常用的设计模式
iOS常用的设计模式有:单例模式.委托模式.观察者模式和MVC模式.下面分别简单介绍. 一:单例模式 我们常用的UIApplication.NSUserdefaults.NSNotificationC ...
- [转]ASP.NET应用程序生命周期趣谈(三) HttpModule
在之前的文章中,我们提到过P_Module(HttpModule)这个能干的程序员哥们儿,它通过在项目经理HttpApplication那里得到的授权,插手整个应用程序级别的事件处理.所有的HttpM ...
- 【iOS 单例设计模式】底层解析与运用
[iOS 单例设计模式]底层解析与运用 一.单例设计名词解释: (官方解释)单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例.(形象比喻)程序 — 公司 单例实例 - 管理 ...
- 趣谈、浅析CRLF和LF
作为程序员,在处理文件和输入输出的时候经常要跟CRLF和LF打交道.可能大家多少知道一些,但总是记不清楚,我也是这样的,因此写下这篇博文,作为记录. 首先,明确他们的意思:CR(回车),LF(换行). ...
- iOS 10推送通知开发
原文地址:Developing Push Notifications for iOS 10,译者:李剑飞 虽然通知经常被过度使用,但是通知确实是一种获得用户关注和通知他们需要更新或行动的有效方式.iO ...
- (七十三)iOS本地推送通知的实现
iOS的推送通知分为本地推送和网络推送两种,如果App处于挂起状态,是可以发送本地通知的,如果已经被杀掉,则只有定时通知可以被执行,而类似于QQ的那种网络消息推送就无法实现了,因为App的网络模块在被 ...
- 趣谈生成函数 =v=
趣谈生成函数 =v= 今天luyouqi在洛谷随机跳题rand出来一道生成函数板子题,然后我给做了(雾 发现小伙伴们还不会生成函数,于是我试着写这篇生成函数简介.(其实我也不怎么会生成函数这么高级的东 ...
随机推荐
- 2016HUAS_ACM暑假集训4A - 递推
利用组合公式C(n,m)=C(n-1,m)+C(n-1,m-1).也就是从n个数里面选择m个数.按递增方式放在每一层循环. 杨辉三角+二项式定理,还真是挺有“意思”的一道题.说实话,非原创.见谅... ...
- POI2012
现在才开始写 POI 是不是太弱了? -Rendezvous 怎么说呢,我发现我的代码好长啊-长啊-长啊-长长长长长长长长长长长长长长长长长长长长长长啊- 大概就是在一个内向树上搞一个类似 lca 的 ...
- 初学Laravel
之前一直用开tp和ot,本来觉得学会一个tp便可走遍天下,tp的确强大.但后来听到很多同行的同学说他们的公司都开始转型往lv走了,我的同学没有学过lv,然而公司给足时间去让他们去学.当然,缺人可能是占 ...
- struct2的structs.xml文件配置There is no Action mapped for action name 问题
很久没写过博客,今天重新开始写,新技术太多,只有通过博客才可以不断积累,本人水平有限,如有错误,欢迎指正,谢谢 今天在MAVEN上配置web project的struct2,发现自己忽略了很多问题,再 ...
- 想让你的java代码更漂亮,用枚举吧
枚举是java 5之后添加的一个重要特性,这个特性不能提高性能,但是能让java程序员写出更优雅的代码. 我之前看到过挺多介绍java枚举的不错的帖子,我也来参与以下这个话题. 1. 枚举基本用法 / ...
- git初学习体会
github:项目版本控制器 git和传统的版本控制器相比,最大的一点是,界面简单,给与非线性开发模式的强有力的支持,完全分布式等. 对于完全分布式的实现,我的理解是这个样子的.这多少要涉及到一点它的 ...
- 命令模式(Command Pattern)
命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开.命令模式是为了解决命令的请求者和命令的实现者之间的耦合关系. 将来自客户端的请求传入一个对象,从而使你可用不同的请求对客户进行参 ...
- Centos 6.5安装oracle 11g
(添加host)一.Centos 6.5 安装图形界面 gnome # yum groupinstall "Desktop" # yum groupinstall "X ...
- oracle数据库从入门到精通
oracle产品线围绕企业开发平台的企业开发平台四大组件:unix,weblogic中间件,java编程语言,oracle数据库oracle 开发主要分两类数据库管理:dba数据库编程:分两部分 ...
- python使用xlrd模块读写excel
1.行列索引均从0开始2.int数据被读成float数据,解决办法,if type(value) == float and value%1 == 0,value= int(value)模块读 #!/u ...