-通知中心

对于很多初学者往往会把iOS中的本地通知、推送通知和iOS通知中心的概念弄混。其实二者之间并没有任何关系,事实上它们都不属于一个框架,前者属于UIKit框架,后者属于Foundation框架。

通知中心实际上是iOS程序内部之间的一种消息广播机制,主要为了解决应用程序内部不同对象之间解耦而设计。它是基于观察者模式设计的,不能跨应用程序进程通信,当通知中心接收到消息之后会根据内部的消息转发表,将消息发送给订阅者。下面是一个简单的流程示意图:

了解通知中心需要熟悉NSNotificationCenter和NSNotification两个类:

NSNotificationCenter:是通知系统的中心,用于注册和发送通知,下表列出常用的方法。

方法 说明
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject 添加监听,参数:
observer:监听者
selector:监听方法(监听者监听到通知后执行的方法)
  name:监听的通知名称
object:通知的发送者(如果指定nil则监听任何对象发送的通知)
- (id <NSObject>)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block 添加监听,参数:
name:监听的通知名称
object:通知的发送者(如果指定nil则监听任何对象发送的通知)
queue:操作队列,如果制定非主队线程队列则可以异步执行block
block:监听到通知后执行的操作
- (void)postNotification:(NSNotification *)notification 发送通知,参数:
notification:通知对象
- (void)postNotificationName:(NSString *)aName object:(id)anObject 发送通知,参数:
aName:通知名称
anObject:通知发送者
- (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo 发送通知,参数:
aName:通知名称
anObject:通知发送者
aUserInfo:通知参数
- (void)removeObserver:(id)observer 移除监听,参数:
observer:监听对象
- (void)removeObserver:(id)observer name:(NSString *)aName object:(id)anObject 移除监听,参数:
observer:监听对象
aName:通知名称
anObject:通知发送者

NSNotification:代表通知内容的载体,主要有三个属性:name代表通知名称,object代表通知的发送者,userInfo代表通知的附加信息。

虽然前面的文章中从未提到过通知中心,但是其实通知中心我们并不陌生,前面文章中很多内容都是通过通知中心来进行应用中各个组件通信的,只是没有单独拿出来说而已。例如前面的文章中讨论的应用程序生命周期问题,当应用程序启动后、进入后台、进入前台、获得焦点、失去焦点,窗口大小改变、隐藏等都会发送通知。这个通知可以通过前面NSNotificationCenter进行订阅即可接收对应的消息,下面的示例演示了如何添加监听获得UIApplication的进入后台和获得焦点的通知:

//
//  KCMainViewController.m
//  NotificationCenter
//
//  Created by Kenshin Cui on 14/03/27.
//  Copyright (c) 2014年 cmjstudio. All rights reserved.
//#import "KCMainViewController.h"@interface KCMainViewController ()@end@implementation KCMainViewController- (void)viewDidLoad {[super viewDidLoad];[self addObserverToNotificationCenter];}#pragma mark 添加监听
-(void)addObserverToNotificationCenter{/*添加应用程序进入后台监听* observer:监听者* selector:监听方法(监听者监听到通知后执行的方法)* name:监听的通知名称(下面的UIApplicationDidEnterBackgroundNotification是一个常量)* object:通知的发送者(如果指定nil则监听任何对象发送的通知)*/[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:[UIApplication sharedApplication]];/* 添加应用程序获得焦点的通知监听* name:监听的通知名称* object:通知的发送者(如果指定nil则监听任何对象发送的通知)* queue:操作队列,如果制定非主队线程队列则可以异步执行block* block:监听到通知后执行的操作*/NSOperationQueue *operationQueue=[[NSOperationQueue alloc]init];[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification object:[UIApplication sharedApplication] queue:operationQueue usingBlock:^(NSNotification *note) {NSLog(@"Application become active.");}];
}#pragma mark 应用程序启动监听方法
-(void)applicationEnterBackground{NSLog(@"Application enter background.");
}
@end

当然很多时候使用通知中心是为了添加自定义通知,并获得自定义通知消息。在前面的文章“iOS开发系列--视图切换”中提到过如何进行多视图之间参数传递,其实利用自定义通知也可以进行参数传递。通常一个应用登录后会显示用户信息,而登录信息可以通过登录界面获取。下面就以这样一种场景为例,在主界面中添加监听,在登录界面发送通知,一旦登录成功将向通知中心发送成功登录的通知,此时主界面中由于已经添加通知监听所以会收到通知并更新UI界面。

主界面KCMainViewController.m:

//
//  KCMainViewController.m
//  NotificationCenter
//
//  Created by Kenshin Cui on 14/03/27
//  Copyright (c) 2014年 cmjstudio. All rights reserved.
//#import "KCMainViewController.h"
#import "KCLoginViewController.h"
#define UPDATE_LGOGIN_INFO_NOTIFICATION @"updateLoginInfo"@interface KCMainViewController (){UILabel *_lbLoginInfo;UIButton *_btnLogin;
}@end@implementation KCMainViewController- (void)viewDidLoad {[super viewDidLoad];[self setupUI];
}-(void)setupUI{UILabel *label =[[UILabel alloc]initWithFrame:CGRectMake(0, 100,320 ,30)];label.textAlignment=NSTextAlignmentCenter;label.textColor=[UIColor colorWithRed:23/255.0 green:180/255.0 blue:237/255.0 alpha:1];_lbLoginInfo=label;[self.view addSubview:label];UIButton *button=[UIButton buttonWithType:UIButtonTypeSystem];button.frame=CGRectMake(60, 200, 200, 25);[button setTitle:@"登录" forState:UIControlStateNormal];[button addTarget:self action:@selector(loginOut) forControlEvents:UIControlEventTouchUpInside];_btnLogin=button;[self.view addSubview:button];
}-(void)loginOut{//添加监听[self addObserverToNotification];KCLoginViewController *loginController=[[KCLoginViewController alloc]init];[self presentViewController:loginController animated:YES completion:nil];
}/***  添加监听*/
-(void)addObserverToNotification{[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateLoginInfo:) name:UPDATE_LGOGIN_INFO_NOTIFICATION object:nil];
}/***  更新登录信息,注意在这里可以获得通知对象并且读取附加信息*/
-(void)updateLoginInfo:(NSNotification *)notification{NSDictionary *userInfo=notification.userInfo;_lbLoginInfo.text=userInfo[@"loginInfo"];_btnLogin.titleLabel.text=@"注销";
}-(void)dealloc{//移除监听[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end

登录界面KCLoginViewController.m:

//
//  KCLoginViewController.m
//  NotificationCenter
//
//  Created by Kenshin Cui on 14/03/27.
//  Copyright (c) 2014年 cmjstudio. All rights reserved.
//#import "KCLoginViewController.h"
#define UPDATE_LGOGIN_INFO_NOTIFICATION @"updateLoginInfo"@interface KCLoginViewController (){UITextField *_txtUserName;UITextField *_txtPassword;
}@end@implementation KCLoginViewController- (void)viewDidLoad {[super viewDidLoad];[self setupUI];
}/***  UI布局*/
-(void)setupUI{//用户名UILabel *lbUserName=[[UILabel alloc]initWithFrame:CGRectMake(50, 150, 100, 30)];lbUserName.text=@"用户名:";[self.view addSubview:lbUserName];_txtUserName=[[UITextField alloc]initWithFrame:CGRectMake(120, 150, 150, 30)];_txtUserName.borderStyle=UITextBorderStyleRoundedRect;[self.view addSubview:_txtUserName];//密码UILabel *lbPassword=[[UILabel alloc]initWithFrame:CGRectMake(50, 200, 100, 30)];lbPassword.text=@"密码:";[self.view addSubview:lbPassword];_txtPassword=[[UITextField alloc]initWithFrame:CGRectMake(120, 200, 150, 30)];_txtPassword.secureTextEntry=YES;_txtPassword.borderStyle=UITextBorderStyleRoundedRect;[self.view addSubview:_txtPassword];//登录按钮UIButton *btnLogin=[UIButton buttonWithType:UIButtonTypeSystem];btnLogin.frame=CGRectMake(70, 270, 80, 30);[btnLogin setTitle:@"登录" forState:UIControlStateNormal];[self.view addSubview:btnLogin];[btnLogin addTarget:self action:@selector(login) forControlEvents:UIControlEventTouchUpInside];//取消登录按钮UIButton *btnCancel=[UIButton buttonWithType:UIButtonTypeSystem];btnCancel.frame=CGRectMake(170, 270, 80, 30);[btnCancel setTitle:@"取消" forState:UIControlStateNormal];[self.view addSubview:btnCancel];[btnCancel addTarget:self action:@selector(cancel) forControlEvents:UIControlEventTouchUpInside];
}#pragma mark 登录操作
-(void)login{if ([_txtUserName.text isEqualToString:@"kenshincui"] && [_txtPassword.text isEqualToString:@"123"] ) {//发送通知[self postNotification];[self dismissViewControllerAnimated:YES completion:nil];}else{//登录失败弹出提示信息UIAlertView *alertView=[[UIAlertView alloc]initWithTitle:@"系统信息" message:@"用户名或密码错误,请重新输入!" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:nil];[alertView show];}}#pragma mark 点击取消
-(void)cancel{[self dismissViewControllerAnimated:YES completion:nil];
}/***  添加通知,注意这里设置了附加信息*/
-(void)postNotification{NSDictionary *userInfo=@{@"loginInfo":[NSString stringWithFormat:@"Hello,%@!",_txtUserName.text]};NSLog(@"%@",userInfo);NSNotification *notification=[NSNotification notificationWithName:UPDATE_LGOGIN_INFO_NOTIFICATION object:self userInfo:userInfo];[[NSNotificationCenter defaultCenter] postNotification:notification];
//也可直接采用下面的方法
//    [[NSNotificationCenter defaultCenter] postNotificationName:UPDATE_LGOGIN_INFO_NOTIFICATION object:self userInfo:userInfo];}
@end

运行效果:

注意:

通过上面的介绍大家应该可以发现其实通知中心是一种低耦合设计,和前面文章中提到的代理模式有异曲同工之妙。相对于后者而言,通知中心可以将一个通知发送给多个监听者,而每个对象的代理却只能有一个。当然代理也有其优点,例如使用代理代码分布结构更加清晰,它不像通知一样随处都可以添加订阅等,实际使用过程中需要根据实际情况而定。

本作品采用知识共享署名 2.5 中国大陆许可协议进行许可,欢迎转载,演绎或用于商业目的。但转载请注明来自崔江涛(KenshinCui),并包含相关链接。

NotificationCenter相关推荐

  1. RxSwift之NotificationCenter的使用和自定义

    一.系统通知的注册与响应 ① 监听应用进入后台的通知 现有如下需求:程序编译运行后,当按下设备的 home 键,程序进入后台的同时会在控制台中输出相关信息. 程序进入后台时除了会执行 AppDeleg ...

  2. cocos2dx[3.2](21)——观察者模式NotificationCenter

    [唠叨] 观察者模式 也叫订阅/发布(Subscribe/Publish)模式,是 MVC( 模型-视图-控制器)模式的重要组成部分. 举个例子:邮件消息的订阅.  比如我们对51cto的最新技术动态 ...

  3. Unity 3D 消息事件系统 NotificationCenter、CEventDispatcher事件分发机制

    版本:unity 5.4.1  语言:C# 实战核心技术这本书来到了第三章,这里给了一个消息事件系统,这是几乎每一个游戏系统都会用到的一个常用技术,非常好用,但如果你add之后忘记remove的话.. ...

  4. 【ios开发/Xcode】使用UITableView完成学生信息及成绩的显示

    [ios开发/Xcode]使用UITableView完成学生信息及成绩的显示 设计思想 实现效果 源代码 设计思想 首先创建所有页面的故事版,包括,登录.注册与成绩页面 接着设置故事版的关联代码,如下 ...

  5. swift3.0三种反向传值

    一 :通知 1.通知传值所用方法 // MARK: - private methods(内部接口) let NotifMycation = NSNotification.Name(rawValue:& ...

  6. iOS开发系列--通知与消息机制

    http://www.cocoachina.com/ios/20150318/11364.html 概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣 ...

  7. iPhone开发笔记(1)MPMoviePlayerController的用法和播放时只有声音没有图像的解决办法...

    为什么80%的码农都做不了架构师?>>>    MPMoviePlayerController类是一个功能非常强大的类,它可以播放MOV.MP4.MPV.M4V.3GP.MP3.AI ...

  8. 如何提高 Xcode 的编译速度

    本文总结自 WWDC 2018 building faster in xcode 该 Session 通过一系列的实践来实现 Xcode 的快速编译,共阐述了六个大方面,分别是: 将编译过程并行化 通 ...

  9. Unity 消息发送机制 解析

    1.思考 消息发送机制,也可以叫做观察者设计模式(应该是这样的). 通俗易懂点讲,就是 一个物体发出消息,另外一个,或者几个物体可以同时接收到这一消息并作出各自不同的行为(反馈,处理). 那么,首先, ...

最新文章

  1. oracle 11g wm_concat 、 listagg 函数的使用(合并数据)
  2. svm硬间隔与软间隔
  3. 二分图的最佳完美匹配(模板)
  4. kotlin 计算平方_Kotlin程序来计算复利
  5. javascript学习系列(13):数组中的concat方法
  6. 全国计算机考试上传不了照片,报考2018计算机等级考试对上传照片有何要求?...
  7. python实现jpeg转jpg
  8. 点餐系统mysql设计,SpringBoot 微信点餐系统 1:数据库表设计
  9. Tox协议官方文档翻译(一)
  10. 贪吃蛇python游戏
  11. 缔造企鹅:产品经理是这样炼成的札记-技巧
  12. 小白如何装重装操作系统(使用PE辅助)
  13. java报错Error attempting to get column ‘XXX’ from result set. Cause: java.sql.怎么解决
  14. PLC转行嵌入式软件开发的辛路历程
  15. 高精度在线计时器(秒表)
  16. js开根号_在JavaScript中使用开平方根的sqrt()方法
  17. 涉案金额600万!微粒贷诈骗团伙被警方一锅端
  18. 昆明理工大学知道计算机答案,昆明理工大学 计算机基础教材参考答案(1-6章)
  19. VS2017项目配置X86改配置x64位
  20. 老师不能被计算机取代的英文作文,2019专八作文范文赏析:老师不能被取代

热门文章

  1. COM:细菌-真菌的平衡维持动植物健康
  2. Nat. Biotechnol.扩增子测序革命—用16S及18S rRNA全长进行微生物多样性研究
  3. R语言使用ggplot2包使用geom_violin函数绘制分组小提琴图(配置显示均值、中位数)实战
  4. R语言ggplot2可视化绘制分组水平条形图并在条形图的各种位置添加数值标签实战
  5. pandas计算滑动窗口中的最小值实战(Rolling Minimum in a Pandas Column):计算单数据列滑动窗口中的最小值、计算多数据列滑动窗口中的最小值
  6. 密度聚类OPTICS算法
  7. 列举一些RNN类模型的常见使用形式以及常见的应用
  8. python代码打印二叉树某一特定层的节点
  9. c语言程序设计电大作业,电大C语言程序设计第1234次作业及答案
  10. R语言绘图-常用参数