NSNotifcation & NSNotificationCenter
常拿来和Delegate
、Block
作比较。作为一种消息通知机制,跨层传递消息是其最常见的使用场景。具体怎么使用相信大家早已经烂熟于心。众所周知,NSNotifcation & NSNotificationCenter
是使用观察者设计模式实现的,但是对于具体到代码大部分工程师包括我在内估计都没有深究。最近闲下来,翻翻资料找找灵感,动手实现了一个自己的NSNotifcation & NSNotificationCenter
分享给大家。
结合日常使用与上图,一起来分析一下整个过程:
打个比方,可能不太恰当。NSNotificationCenter
就像村里面的大喇叭,村里面有啥新闻可以通过它广而告之。这个时候每一个村民都是一个注册了的observer
,如果这个新闻和自己有关系就会作出反应。
要模拟这个场景,我们需要做哪些工作
最基本的,要有一个大喇叭NSNotificationCenter
,而且大喇叭能够发广播也就要有一个NSNotification
的广播对象,还要一个村民对象。
继续分析,大喇叭要广播啊,那就需要一个post广播的API。还需要对应每个广播的受众,这就需要一个能让村民们注册自己的偏爱的API。
好了,动动小手吧!
搞一个大喇叭叫SPNotificationCenter
,因为要跨层使用最好是一个单例,它有两个API:一个post广播,一个注册村民。
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject
{ // 添加“村民”到本村户口名单
SPObserverModel *observerModel = [[SPObserverModel alloc] init];
observerModel.observer = observer; // 村民本体
observerModel.selector = aSelector; // 村民听到广播后的操作
observerModel.notificationName = aName; // 村民喜欢的广播
observerModel.object = anObject; // 广播具体内容
[self.observers addObject:observerModel];
}
- (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo
{
SPNotification *notification = [[SPNotification alloc] initWithName:aName object:anObject userInfo:aUserInfo]; // 广播对象
[self.observers enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { // 遍历本村村民
SPObserverModel *observerModel = obj;
id observer = observerModel.observer;
SEL selector = observerModel.selector;
if ([observerModel.notificationName isEqualToString:aName]) { // 找到喜欢本次广播的村民,村民做出响应
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[observer performSelector:selector withObject:notification];
#pragma clang diagnostic pop
}
}];
}
以上就是核心的逻辑了。
网友评论