写在前面
关于NSNotificationCenter 大家并不陌生,今天我们就来简单的聊聊。
NSNotificationCenter and Delegate 都是可以做到通知去做某事
,NSNotificationCenter 可以通知多个,Delegate 只能通知一个。这是Notification的优点,但同时也是它的缺点。
- 在多人合作的项目中,我们经常会出现一些尴尬的情况,发出一个通知后,数据就被其他类监听,然后数据就被莫名其妙的修改了,这种问题如果开始没有想到是通知的锅,就很难排查了
- 发出通知后可以在所有类进行监听,就很强的侵入性。对数据的流动和数据的标识时不友好的
- 同时发出去的数据并不知道类型,只能和发出通知的人进行约定,然后进行类型判定,可读性不高
- 监听通知后,必须手动释放,不然就会造成内存泄漏
- other 留言区我们再探讨
基于上面的方案:我们尝试的做了一个使用协议替代NSNotificationCenter 的方案。这个方案是我之前的一位同事提出的。。。。
ProtocolFinder
- 一种使用协议代替NSNotificationCenter 的方案
- 使用
NSPointerArray
保存实现协议,需要监听数据的实例,可以达到当类被释放后,可以自动释放数据
注册表
将类和协议按照如下的格式保存,类和协议是多对多的关系
/**
protocol 注册记录表
p:协议名
obj:class
{
p1:[obj1,obj2,obj3],
p2:[obj1,obj2,obj3],
p3:[obj1,obj2,obj3],
...
...
pn:[obj1,obj2,obj3],
}
*/
使用
Use
- 定义协议
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@protocol LCCTestProtocol <NSObject>
- (void)test:(NSString *)param;
- (void)test2:(NSString *)param param2:(NSString *)param2;
@end
- 发出通知
/// 发出通知
// 只有一个参数时
[[ProtocolFinder defaultFinder] execute:@protocol(LCCTestProtocol) selector:@selector(test:) withObj:@"xxxx"];
/// 有多个参数时
[[ProtocolFinder defaultFinder] execute:@protocol(LCCTestProtocol) selector:@selector(test2:param2:) run:^(id _Nonnull obj) {
[obj test2:@"xxx" param2:@"yyy"];
}];
//OR
NSArray * objs = [[ProtocolFinder defaultFinder] findObjForProtocol:@protocol(LCCTestProtocol)];
for (id<LCCTestProtocol> obj in objs) {
if([obj respondsToSelector:@selector(test2:param2:)]){
[obj test2:@"xxx" param2:@"yyy"];
}
}
- 接收通知
#import "LCCViewController.h"
#import "ProtocolFinder.h"
#import "LCCTestProtocol.h"
@interface LCCViewController ()<LCCTestProtocol>
@end
@implementation LCCViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//注册监听
[[ProtocolFinder defaultFinder] registerObj:self forProtocols:@[@protocol(LCCTestProtocol)]];
}
// 这里实现对应的协议就可以监听了
- (void)test:(NSString *)param{
NSLog(@"%s",__func__);
}
- (void)test2:(NSString *)param param2:(NSString *)param2{
NSLog(@"%s",__func__);
}
Pod
pod 'LCCProtocolFinder'