简介
通知中心是iOS内部之间的一种消息广播机制,主要为了解决应用程序内部不同对象之间解耦而设计。它是基于观察者模式设计的,不能跨应用程序进程通信,当通知中心接收到消息之后会根据内部的消息转发表,将消息发送给订阅者。
实现原理
- 应用程序中需要订阅通知的对象,会向通告中心(NSNotificationCenter类的实例)注册,从而成为该事件的监听者。在注册过程中,监听者需要指定方法供通告中心在事件发生时调用。
- 监听对象发生变化后,对象给通告中心发一个通知(NSNotification的实例)。该通告对象包括识别通告的标志、发布通告的对象ID和可选的附加信息字典。
- 通告中心发送消息到每个已注册的监听者,调用监听者指定的方法会将通告传给这些监听者。
自定义实现NSNotificationCenter
创建CustomNotificationCenter单例类,实现一个单例类。
// CustomNotificationCenter.h
@interface CustomNotificationCenter : NSObject
+ (instancetype)defaultCenter;
// 注册通知
- (void)addObserver:(nonnull id)observer selector:(nonnull SEL)selector name:(NSString *)name;
// 发送通知
- (void)postNotificationName:(NSString *)name;
// 移出通知
- (void)removeObserver:(nonnull id)observer;
@end
// CustomNotificationCenter.m
#import "CustomNotificationCenter.h"
static CustomNotificationCenter *notificationCenter;
@interface CustomNotificationCenter()
@property (nonatomic, strong) NSMutableDictionary *dataDic;
@end
@implementation CustomNotificationCenter
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (notificationCenter == nil) {
notificationCenter = [super allocWithZone:zone];
}
});
return notificationCenter;
}
+ (instancetype)defaultCenter {
return [[self alloc]init];
}
// 注册通知
- (void)addObserver:(nonnull id)observer selector:(nonnull SEL)selector name:(NSString *)name {
CustomNotificationModel *notiModel = [[CustomNotificationModel alloc]init];
notiModel.name = name;
notiModel.observer = observer;
notiModel.selector = selector;
if ([self.dataDic.allKeys containsObject:notiModel.name]) {
NSMutableArray *array = (NSMutableArray *)self.dataDic[name];
[array addObject:notiModel];
}else {
NSMutableArray *array = [NSMutableArray array];
[array addObject:notiModel];
[self.dataDic setValue:array forKey:name];
NSLog(@"1234");
}
}
// 发送通知
- (void)postNotificationName:(NSString *)name {
if (![self.dataDic.allKeys containsObject:name]) {
return;
}
NSArray *array = (NSArray *)self.dataDic[name];
[array enumerateObjectsUsingBlock:^(CustomNotificationModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj.observer respondsToSelector:obj.selector]) {
((void (*)(id, SEL))[obj.observer methodForSelector:obj.selector])(obj.observer, obj.selector);
}
}];
}
// 移出通知
- (void)removeObserver:(nonnull id)observer {
}
- (NSMutableDictionary *)dataDic {
if (_dataDic == nil) {
_dataDic = [NSMutableDictionary dictionary];
}
return _dataDic;
}
@end
创建CustomNotificationModel类,注册通知时保存的参数。
// CustomNotificationModel.h
@interface CustomNotificationModel : NSObject
// 通知字符串名称
@property (nonatomic, copy) NSString *name;
// 观察者对象
@property (nonatomic, weak) id observer;
// 执行方法
@property (nonatomic, assign) SEL selector;
@end
// CustomNotificationModel.m
@implementation CustomNotificationModel
@end
添加通知方法
// CustomNotificationCenter.h
// 注册通知
- (void)addObserver:(nonnull id)observer selector:(nonnull SEL)selector name:(NSString *)name;
// 发送通知
- (void)postNotificationName:(NSString *)name;
// 移出通知
- (void)removeObserver:(nonnull id)observer;
实现方法
// CustomNotificationCenter.m
// 注册通知
- (void)addObserver:(nonnull id)observer selector:(nonnull SEL)selector name:(NSString *)name {
CustomNotificationModel *notiModel = [[CustomNotificationModel alloc]init];
notiModel.name = name;
notiModel.observer = observer;
notiModel.selector = selector;
if ([self.dataDic.allKeys containsObject:notiModel.name]) {
NSMutableArray *array = (NSMutableArray *)self.dataDic[name];
[array addObject:notiModel];
}else {
NSMutableArray *array = [NSMutableArray array];
[array addObject:notiModel];
[self.dataDic setValue:array forKey:name];
NSLog(@"1234");
}
}
// 发送通知
- (void)postNotificationName:(NSString *)name {
if (![self.dataDic.allKeys containsObject:name]) {
return;
}
NSArray *array = (NSArray *)self.dataDic[name];
[array enumerateObjectsUsingBlock:^(CustomNotificationModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj.observer respondsToSelector:obj.selector]) {
((void (*)(id, SEL))[obj.observer methodForSelector:obj.selector])(obj.observer, obj.selector);
}
}];
}
// 移出通知
- (void)removeObserver:(nonnull id)observer {
NSMutableArray *nameArray = [NSMutableArray array];
NSArray *keys = self.dataDic.allKeys;
for (int i = 0; i < keys.count; i ++) {
NSArray *values = [self.dataDic objectForKey:keys[i]];
for (CustomNotificationModel *model in values) {
id ddd = model.observer;
NSLog(@"%@",ddd);
if (model.observer == observer) {
[nameArray addObject:model.name];
}
}
}
if (nameArray.count != 0) {
[self.dataDic removeObjectsForKeys:nameArray];
}
}
使用
// 注册通知
[[CustomNotificationCenter defaultCenter] addObserver:self selector:@selector(testNotification) name:@"CustomNotificationCenter"];
// 发送通知
[[CustomNotificationCenter defaultCenter] postNotificationName:@"CustomNotificationCenter"];
// 移出通知
[[CustomNotificationCenter defaultCenter] removeObserver:self];
参考
iOS NSNotificationCenter通知中心的实现原理