IOS消息分发(广播)机制

2024-09-06 00:48
文章标签 广播 ios 消息 机制 分发

本文主要是介绍IOS消息分发(广播)机制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在IOS中,提供了通知机制(Notification),可以在对象间传递和接受信息。传递和接受信息的对象间甚至不需要知道对方的存在。究其本质来说,其实是设计模式中的观察者模式的应用。

通知机制

设想这么一个场景:我开发了一款pdf阅读器,当手机上的另一个App打开pdf文件时,通过Open in,选择我的pdf阅读器打开。这时候我的pdf阅读器会被lanuch,同时在其App delegate中application:openURL方法会被调用,在这里我可以获得要打开的pdf文件的URL。然后,我想在App的ViewController中通过调用其他方法来渲染显示pdf文件。那么问题来了,默认的App delegate是和程序的ViewController层面没有联系的,即它不知道ViewController Object的存在,那么我怎么通知ViewController来渲染打开pdf文件并将文件的URL传递过去呢?

可能有人想到通过在App delegate中定义属性记录URL,再在ViewController中通过sharedApplication方式获取。但这种方式我们应该何时调用渲染函数来打开pdf文件呢?

一种更好的方式,就是使用IOS中的Notification机制。

Notification机制允许我们在同一个设备上的单个App中,或多个App间传递消息,甚至在不同设备间传递消息。

Notification由三部分组成:发送消息者、消息中心(负责接送及转发消息)、消息订阅者三个部分。他们的关系如下图所示:




如图所示,Notification机制的流程为:

1、消息发出者(sender)与消息接受者(observer)通过Notification Center建立关系,sender和observer之间互相不知道对方的存在。

2、observer向Notification center注册感兴趣的消息(同一个消息可以被多次注册,这样observer会多次得到相同的消息通知)。

3、sender向Notification center发送消息。

4、Notification center接收到来自sender消息,自动根据注册信息向感兴趣的Observer转发消息。

5、Observer获得来自Notification center的消息处理。

Notification 实例

消息机制能够在同一App的各对象间、不同App间传递消息,这里,就先结合在单个App中的各对象间传递消息为例,来说明如何在代码中使用消息的。


还是以pdf阅读器为例,在App delegate的Open URL方法中,我们获知App因为打开文件而被打开,同时可以获取文件URL地址。这里我们发出一个名称OpenPDF的消息,同时将文件的URL地址作为object参数传递出去。

[objc]  view plain copy
  1. -(BOOL) application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation  
  2. {  
  3.     NSNotificationCenter* notify = [NSNotificationCenter defaultCenter]; // 获取Notification center对象,默认每个APP均有一个单例defaultCenter  
  4.       
  5.     [notify postNotificationName:@"OpenPDF" object:url];  
  6.     return YES;  
  7. }  


上面的处理中,有这么几点:

1、首先获得NSNotificationCenter对象,这里我们通过类方法获取了一个defaultCenter对象。在IOS中,每个App中都会有一个系统默认的defaultCenter对象。

2、我们向Notification center发送消息,调用了postNotificationName:object:方法。其实在该方法中,我们同时创建了一个Notification对象,该方法会将该消息对象发送到notification center中。(其实我们也可以先创建一个Notification对象,再通过调用方法发送该对象,但是现在使用的方法更简洁)

在IOS中,消息也是一个对象的形式存在的,其有三个属性如下:

[objc]  view plain copy
  1. @interface NSNotification : NSObject <NSCopying, NSCoding>  
  2.   
  3. @property (readonlycopyNSString *name;        // 消息名称  
  4. @property (readonlyretainid object;           // 消息附加的对象信息  
  5. @property (readonlycopyNSDictionary *userInfo;// 消息附加的用户自定义扩展信息  

上面三个属性的具体内容都是由sender定义的,其中name可以让我们区别是什么消息,而object和userInfor则可以附带一些消息发出时的附加信息供消息接受者处理。(object属性通常会设置为消息发出者自身self,这样observer就可以通过订阅时指定name 和 object属性来确定感兴趣的消息,并指定其来自那个object)。

3、observer注册感兴趣的消息到notification center,并指明处理消息的selector或块。

这里,在ViewController的viewDidLoad中,我注册了感兴趣的通知,OpenPDF。并指明处理的selector为openPDFAction:

[objc]  view plain copy
  1. - (void)viewDidLoad {  
  2.     [super viewDidLoad];  
  3.     // Do any additional setup after loading the view, typically from a nib.  
  4.     NSNotificationCenter* notify = [NSNotificationCenter defaultCenter];  
  5.     [notify addObserver:self selector:@selector(openPDFAction:) name:@"OpenPDF" object:nil];   
  6. }  

在订阅消息函数中,我们并没有指定要订阅那个object,所以不管是那个sender的消息,只要名字等于OpenPDF,则Notification center就会通知我们,并调用我们的处理函数openPDFAction。

4、处理函数的定义一般如下,其参数仅有一个,就是被转发过来的Notification对象,同时,没有返回值(因为一个消息可能会被转发至多个Observer,对于返回值来说就没有必要了,否则,你应使用那个处理函数的返回值呢?)

[objc]  view plain copy
  1. -(void) openPDFAction:(NSNotification*) sender  
  2. {  
  3.     NSURL* URL = (NSURL*)[sender object];  
  4.     if (URL) {  
  5.         self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:URL];  
  6.         [self.documentInteractionController setDelegate:self];  
  7.         [self.documentInteractionController presentPreviewAnimated:YES];  
  8.     }  
  9.   
  10. }  

OK,这样我们就完成了一个消息的处理流程了:sender发出消息到Notification center,Observer 注册感兴趣的消息到Notification center,Notification center在有消息时,会自动将消息发送给感兴趣的Observer。在这个流程中,sender和Observer始终不知道对方的存在,他们是通过Notification center建立联系的。


Notification机制的一些细节

1、在单个App中,我们通过NSNotificationCenter对象接收分发消息。若要再多个App间传递消息,则需要NSDistributedNotificationCenter对象。

2、利用NSNotificationCenter对象分发notification是同步的,即直到所有的Observer均接收到消息并处理完成后,调用消息分发的函数才会返回。若想异步处理消息分发,可以借助Notification Queues(一个为NSNotificationCenter对像配备的消息缓存)。

3、消息分发一般来说是不会跨线程的。对于NSNotificationCenter,消息只会在发出消息的线程中传递。对于NSDistributedNotificationCenter,消息只会传递到另一个App的主线程上。

若要实现消息的跨线程分发,一种方法是可以实现自定义的消息缓冲(不是系统的NSNotificationQueue对象),让其在正确的线程上接受消息,然后再像目标线程转发消息。

4、跨App的消息通过系统的转发中心转发,它会消耗大量系统资源,同时不能够保证消息的实时性。若系统中又过多的消息需要传递,IOS系统其实会丢弃一些跨App消息。同时,通过NSDistributedNotificationCenter传递的消息,其object参数仅能是NSString对象,在用户的自定义字典参数中,仅能够存储property list类型。

这篇关于IOS消息分发(广播)机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1140524

相关文章

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

MySQL中的锁机制详解之全局锁,表级锁,行级锁

《MySQL中的锁机制详解之全局锁,表级锁,行级锁》MySQL锁机制通过全局、表级、行级锁控制并发,保障数据一致性与隔离性,全局锁适用于全库备份,表级锁适合读多写少场景,行级锁(InnoDB)实现高并... 目录一、锁机制基础:从并发问题到锁分类1.1 并发访问的三大问题1.2 锁的核心作用1.3 锁粒度分

java向微信服务号发送消息的完整步骤实例

《java向微信服务号发送消息的完整步骤实例》:本文主要介绍java向微信服务号发送消息的相关资料,包括申请测试号获取appID/appsecret、关注公众号获取openID、配置消息模板及代码... 目录步骤1. 申请测试系统2. 公众号账号信息3. 关注测试号二维码4. 消息模板接口5. Java测试

Redis的持久化之RDB和AOF机制详解

《Redis的持久化之RDB和AOF机制详解》:本文主要介绍Redis的持久化之RDB和AOF机制,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述RDB(Redis Database)核心原理触发方式手动触发自动触发AOF(Append-Only File)核

PostgreSQL中MVCC 机制的实现

《PostgreSQL中MVCC机制的实现》本文主要介绍了PostgreSQL中MVCC机制的实现,通过多版本数据存储、快照隔离和事务ID管理实现高并发读写,具有一定的参考价值,感兴趣的可以了解一下... 目录一 MVCC 基本原理python1.1 MVCC 核心概念1.2 与传统锁机制对比二 Postg

Maven 配置中的 <mirror>绕过 HTTP 阻断机制的方法

《Maven配置中的<mirror>绕过HTTP阻断机制的方法》:本文主要介绍Maven配置中的<mirror>绕过HTTP阻断机制的方法,本文给大家分享问题原因及解决方案,感兴趣的朋友一... 目录一、问题场景:升级 Maven 后构建失败二、解决方案:通过 <mirror> 配置覆盖默认行为1. 配置示

Redis过期删除机制与内存淘汰策略的解析指南

《Redis过期删除机制与内存淘汰策略的解析指南》在使用Redis构建缓存系统时,很多开发者只设置了EXPIRE但却忽略了背后Redis的过期删除机制与内存淘汰策略,下面小编就来和大家详细介绍一下... 目录1、简述2、Redis http://www.chinasem.cn的过期删除策略(Key Expir

Go语言中Recover机制的使用

《Go语言中Recover机制的使用》Go语言的recover机制通过defer函数捕获panic,实现异常恢复与程序稳定性,具有一定的参考价值,感兴趣的可以了解一下... 目录引言Recover 的基本概念基本代码示例简单的 Recover 示例嵌套函数中的 Recover项目场景中的应用Web 服务器中

C++ RabbitMq消息队列组件详解

《C++RabbitMq消息队列组件详解》:本文主要介绍C++RabbitMq消息队列组件的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. RabbitMq介绍2. 安装RabbitMQ3. 安装 RabbitMQ 的 C++客户端库4. A

Jvm sandbox mock机制的实践过程

《Jvmsandboxmock机制的实践过程》:本文主要介绍Jvmsandboxmock机制的实践过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、背景二、定义一个损坏的钟1、 Springboot工程中创建一个Clock类2、 添加一个Controller