美文网首页
iOS-简单实现NSNotificationCenter

iOS-简单实现NSNotificationCenter

作者: 大风车__ | 来源:发表于2019-07-23 16:29 被阅读0次

1. h文件

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface NotificationCenter : NSObject

- (instancetype)init UNAVAILABLE_ATTRIBUTE;
+ (instancetype)new UNAVAILABLE_ATTRIBUTE;

@property (class, readonly, strong) NotificationCenter *defaultCenter;

- (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSNotificationName)aName object:(nullable id)anObject;

- (void)postNotification:(NSNotification *)notification;
- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject;
- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;

- (void)removeObserver:(id)observer;
- (void)removeObserver:(id)observer name:(nullable NSNotificationName)aName object:(nullable id)anObject;

@end

NS_ASSUME_NONNULL_END

2. m文件

#import "NotificationCenter.h"
#import <objc/message.h>

static NotificationCenter *shareInstance = nil;

@interface ObserverInfo: NSObject
@property(nonatomic, assign) SEL selector;
@property(nonatomic, weak) id observer;
@property(nonatomic, strong) NSNotification *notification;
@end

@implementation ObserverInfo
@end

@interface NotificationCenter()
@property(nonatomic, strong) NSMutableArray<ObserverInfo *> *observers;
@end

@implementation NotificationCenter

- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSNotificationName)aName object:(id)anObject{
    if (!observer || !aSelector) {
        return;
    }
    NSNotification *notification = [NSNotification notificationWithName:aName object:anObject];
    ObserverInfo *info = [ObserverInfo new];
    info.notification = notification;
    info.observer = observer;
    info.selector = aSelector;
    [_observers addObject:info];
}

- (void)postNotificationName:(NSNotificationName)aName object:(id)anObject{
    NSNotification *notification = [NSNotification notificationWithName:aName object:anObject];
    [self postNotification:notification];
}

- (void)postNotificationName:(NSNotificationName)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo{
    NSNotification *notification = [NSNotification notificationWithName:aName object:anObject userInfo:aUserInfo];
    [self postNotification:notification];
}

- (void)postNotification:(NSNotification *)notification{
    if (!notification){
        return;
    }
    [_observers enumerateObjectsUsingBlock:^(ObserverInfo * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([notification.name isEqualToString:obj.notification.name]){
            if (notification.object){
                ((void (*)(id, SEL, id))(void *) objc_msgSend)(obj.observer, obj.selector, notification);
            }else{
                NSNotification *aNotification = [NSNotification notificationWithName:notification.name object:obj.notification.object userInfo:notification.userInfo];
                ((void (*)(id, SEL, id))(void *) objc_msgSend)(obj.observer, obj.selector, aNotification);
            }
        }
    }];
}

- (void)removeObserver:(id)observer name:(NSNotificationName)aName object:(id)anObject{
    if(!observer){
        return;
    }
    [_observers enumerateObjectsUsingBlock:^(ObserverInfo * _Nonnull obj, NSUInteger idx,  BOOL * _Nonnull stop) {
        NSNotification *notification = obj.notification;
        if(obj.observer == observer
           && notification.object == anObject
           && [notification.name isEqualToString:aName]){
            [self.observers removeObject:obj];
        }
    }];
}

- (void)removeObserver:(id)observer{
    if(!observer){
        return;
    }
    [_observers enumerateObjectsUsingBlock:^(ObserverInfo * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if(obj.observer == observer){
            [self.observers removeObject:obj];
        }
    }];
}

+ (NotificationCenter *)defaultCenter{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        shareInstance = [[self alloc]init];
        shareInstance.observers = [NSMutableArray new];
    });
    return shareInstance;
}
@end

3. 使用

#import "ViewController.h"
#import "NotificationCenter.h"

static NSString * const NotificationName = @"NotificationName";

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    UIButton *add = [[UIButton alloc]init];
    add.frame = CGRectMake(100, 100, 100, 50);
    [add setTitle:@"添加通知" forState:UIControlStateNormal];
    [add setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [add addTarget:self action:@selector(addClicked:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:add];
    
    UIButton *send = [[UIButton alloc]init];
    send.frame = CGRectMake(100, 150, 100, 50);
    [send setTitle:@"发送通知" forState:UIControlStateNormal];
    [send setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [send addTarget:self action:@selector(sendClicked:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:send];
    
    UIButton *delete = [[UIButton alloc]init];
    delete.frame = CGRectMake(100, 200, 100, 50);
    [delete setTitle:@"移除通知" forState:UIControlStateNormal];
    [delete setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [delete addTarget:self action:@selector(deleteClicked:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:delete];
}

- (void)addClicked:(id)sender{
    [[NotificationCenter defaultCenter] addObserver:self selector:@selector(respondsToNotification:) name:NotificationName object:nil];
}

- (void)sendClicked:(id)sender{
    [[NotificationCenter defaultCenter] postNotificationName:NotificationName object:@"数据"];
}

- (void)deleteClicked:(id)sender{
    [[NotificationCenter defaultCenter] removeObserver:self];
}

- (void)respondsToNotification:(NSNotification *)aNotification{
    NSLog(@"%@", aNotification.object);
}
@end

相关文章

网友评论

      本文标题:iOS-简单实现NSNotificationCenter

      本文链接:https://www.haomeiwen.com/subject/afrolctx.html