iOS实现NSNotificationCenter

简介

通知中心是iOS内部之间的一种消息广播机制,主要为了解决应用程序内部不同对象之间解耦而设计。它是基于观察者模式设计的,不能跨应用程序进程通信,当通知中心接收到消息之后会根据内部的消息转发表,将消息发送给订阅者。

实现原理

  1. 应用程序中需要订阅通知的对象,会向通告中心(NSNotificationCenter类的实例)注册,从而成为该事件的监听者。在注册过程中,监听者需要指定方法供通告中心在事件发生时调用。
  2. 监听对象发生变化后,对象给通告中心发一个通知(NSNotification的实例)。该通告对象包括识别通告的标志、发布通告的对象ID和可选的附加信息字典。
  3. 通告中心发送消息到每个已注册的监听者,调用监听者指定的方法会将通告传给这些监听者。

自定义实现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通知中心的实现原理

你可能感兴趣的:(iOS实现NSNotificationCenter)