目标
订阅登录事件LoginEvent,当self dealloc时候自动取消订阅
[QTSub(self, LoginEvent) next:^(LoginEvent *event) {
}];
订阅通知NSNotification,当self dealloc的时候自动取消订阅
//订阅通知name
[QTSubNoti(self,"name") next:^(NSNotification *event) {
}];
//订阅App将要关闭
[[self subscribeAppWillTerminate] next:^(NSNotification *event) {
}];
并且XCode可以自动推断类型
好了,开始啰里八嗦讲原理和设计了,做好准备,文章挺长的。不想看我啰嗦,代码在这里。
Notification的痛点
Cocoa Touch提供了一种消息中心机制:NSNotificationCenter,相信iOS开发者都很熟悉了,
addObserver
订阅通知postNotification
发送通知removeObserver
取消订阅
当然,还有一个接口是比较容易忽略的,就是利用block注册订阅
NSNotificationCenter * center = [NSNotificationCenter defaultCenter];
id<NSObject> token = [center addObserverForName:@"name"
object:nil
queue:nil
usingBlock:^(NSNotification * _Nonnull note) {
}];
[center removeObserver:token]
实际开发中,Notification又有哪些痛点呢?
Name如何管理?
方式一:hardcode在代码里
[center addObserverForName:@"UserLoginNotification" ...]
优点:无需额外的import,松耦合。
缺点:修改和版本管理麻烦
方式二:在相关模块的源文件里,比如登录成功的通知放在登录模块里。
//.h文件
extern NSString * const UserLoginNotification; //登录成功
//.m文件
NSString * const UserLoginNotification = @"UserLoginNotification";
优点:便于修改和版本管理
缺点:需要import引入对应的模块,导致强耦合模块,但是得到的却是弱类型。
有些同学喜欢把name堆到一个头文件里,这种设计理念是不符合软件设计原则的:“接口隔离原则,不应该强制客户端依赖那些他们不需要的接口”。想想也有道理:我不需要的通知为啥让我引入进来对吧?。
弱类型
常见的用Notification传递消息的方式是UserInfo,然后声明各种key