多delegate使用
多delegate的使用
一般在我们使用delegate都知道,是一对一的关系。在目前的项目中,有这样一个需求,在服务端收到了一个下发事件,需要在不同的页面,不同的VC都收到此事件,并进行相应的处理。当然这个用RAC实现很简单,但是目前的项目是一个SDK,如果将ReactiveCocoa引入进来,工程会增大很多,这样明显是不合理的,这个时候,就想到了多代理这个思路。其实也是从之前写的proxy代理类的想法而来。
实现思路
主要是利用OC的runtime,将一个代理类作为中间类,当收到服务器下发的通知时,通过调用代理类的方法,在代理类中实现消息转发机制,将selector转发给各个代理类。
还是看代码。
首先,我们是将各个代理存在中间类中,这样才能转发到各个代理。
@interface PPSMutableDelegate : NSObject- (void)addDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue;- (void)removeDelegate:(id)delegate delegateQueue:(nullable dispatch_queue_t)delegateQueue;- (void)removeDelegate:(id)delegate;- (void)removeAllDelegates;@end
复制代码
在需要监听的delegate中 通过addDelegate将代理添加进去就行,加入queue的目的是为了,在某些收到消息的方法中,需要进行一些异步处理。如果要在主线程中处理,直接放dispatch_get_main_queue()就ok
实现
//代理对象和代理队列持有类
@interface PPSDelegateNode : NSObject@property (nonatomic, weak) id delegate;
@property (nonatomic, strong) dispatch_queue_t delegateQueue;- (id)initWithDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue;@end@implementation PPSDelegateNode- (id)initWithDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue {self = [super init];if (self) {_delegate = delegate;_delegateQueue = delegateQueue;}return self;
}@end复制代码
这就是一个model类,用来存储一下delegate
在具体的PPSMutableDelegate实现中,用了一个NSMutableArray用来储存delegate 在进行消息转发时,遍历数组 转发出去就行,实现也很简单
在实现消息转发时,主要是通过
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
- (void)forwardInvocation:(NSInvocation *)anInvocation;
复制代码
在实现methodSignatureForSelector:方法时,要注意在这个方法中不能返回nil 否则会崩溃的,所以如果delegate中没有找到实现,可以在当前实现一个空的方法
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {for (PPSDelegateNode *node in self.delegateNodes) {id nodeDelegate = node.delegate;NSMethodSignature *result = [nodeDelegate methodSignatureForSelector:aSelector];if (result != nil) {return result;}}return [[self class] instanceMethodSignatureForSelector:@selector(emptyMethod)];
}
复制代码
实现forwardInvocation:
- (void)forwardInvocation:(NSInvocation *)anInvocation {SEL selector = [anInvocation selector];BOOL foundNilDelegate = NO;for (PPSDelegateNode *node in self.delegateNodes) {id nodeDelegate = node.delegate;if ([nodeDelegate respondsToSelector:selector]) {dispatch_async(node.delegateQueue, ^{[anInvocation invokeWithTarget:nodeDelegate];});} else if (nodeDelegate == nil) {foundNilDelegate = YES;//找到了delegate是空的node 需要移除掉}}if (foundNilDelegate) {NSMutableIndexSet *indexSet = [[NSMutableIndexSet alloc] init];NSUInteger i = 0;for (PPSDelegateNode *node in self.delegateNodes) {id nodeDelegate = node.delegate;if (nodeDelegate == nil) {[indexSet addIndex:i];}i++;}[self.delegateNodes removeObjectsAtIndexes:indexSet];}
}
复制代码
注意 还有一个问题需要注意,要重写当前中间类的doesNotRecognizeSelector:方法,不然如果调用super的这个方法,会造成崩溃
demo地址:github.com/yangqian111…
欢迎关注公众号:
多delegate使用相关推荐
- 理解委托(delegate)及为什么要使用委托
委托:是一种定义方法签名的类型. 当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联. 您可以通过委托实例调用方法. 上述为官方说法,理解起来比较难,举个生活中的例子: 某人有三子,让他们各 ...
- swift中delegate与block的反向传值
swift.jpg 入门级 此处只简单举例并不深究,深究我也深究不来.对于初学者来说delegate或block都不是一下子能理解的,所以我的建议和体会就是,理不理解咱先不说,我先把这个格式记住,对就 ...
- 在请求完成后回调delegate的方法。然而回调时经常遇到这种情况:delegate已经被释放...
最近的项目遇到了网络请求,需要在请求完成后回调delegate的方法.然而回调时经常遇到这种情况:delegate已经被释放,这时调用其方法则会引起crash. objc的runtime中有两种判断类 ...
- 异步使用委托delegate --- BeginInvoke和EndInvoke方法
当我们定义一个委托的时候,一般语言运行时会自动帮委托定义BeginInvoke 和 EndInvoke两个方法,这两个方法的作用是可以异步调用委托. 方法BeginInvoke有两个参数: Async ...
- 对delegate进行扩展 打造通用的计时完成方法
连接数据库是程序员经常要做的事情, 通常情况下, 需要连接SQL Server中哪个数据库是已知的, 用户在输入SQL Server的服务器IP.用户名.密码和数据库名字后, 如果所有信息输入正确, ...
- Swift - 委托(delegate)的介绍,及使用样例
1,委托的说明 委托(delegate)是Cocoa的一个术语,表示将一个对象的部分功能转交给另一个对象. 比如对象A希望对象B知道将要发生或已经发生某件事情,对象A可以把对象B的引用存为一个实例变量 ...
- C#中Action与delegate、EventHandler的差异
Action是一个泛型的委托,其内部即使用delegate去实现,当普通的delegate定义的参数与Action个数.类型一致时,两者实现的功能是一样的.只是Action的方式更加简洁.规范.如下: ...
- 【转】iOS开发-Protocol协议及委托代理(Delegate)传值
原文网址:http://www.cnblogs.com/GarveyCalvin/p/4210828.html 前言:因为Object-C是不支持多继承的,所以很多时候都是用Protocol(协议)来 ...
- c# 带返回值的action_C#知识点讲解之C#delegate、event、Action、EventHandler的使用和区别...
今天来讲一讲<C#delegate.event.Action.EventHandler的使用和区别> 目录 所以,event应运而生 所以,EventHandler应运而生 所以,Acti ...
- iOS视图控制器之间delegate传值
2019独角兽企业重金招聘Python工程师标准>>> // ** *为了从ViewControllerB往回传值到ViewControllerA,我们需要使用协议(Protocol ...
最新文章
- Ajax Upload多文件上传插件翻译及中文演示
- Python之pypmml:pypmml的简介、安装、使用方法之详细攻略
- Description Resource Path Location Type Java compiler level does not match the version of the instal
- 在VS Code中执行SQL查询,是怎样一种体验?
- 罗切斯特大学排名计算机排名,罗切斯特大学排名
- Linux安装MySQL-MariaDB版本
- Membership、MembershipUser和Roles类
- 苹果mac三维动画设计渲染软件:Cinema 4D R20 (c4d r20)
- 简述MAC地址与IP地址的关系
- OPTEE的系统调用
- 【ChinaDRM】符合ChinaDRM GY/T 277-2019标准的码流分析系统
- SLAM学习——BA(Bundle Adjustment)与图优化
- webuploader 手机端上传图片默认打开相机 改为选择相册
- 浮山中学2021年高考成绩查询入口,浮山中学2019年高考成绩通报,第二波震撼来袭...
- 支付宝小程序-实名认证流程讲解
- Ubuntu 安装 uWSGI
- Linux——(1)基本命令
- origin9语言设置中文_Kali设置中文
- 仿知音漫画网站源码 PC+手机端 帝国cms7.5内核
- 设置 Linux 别名命令 alias 永久生效的方法