XMCNotificationCenter里面方法不多,使用简单,先定义协议如UserObserver,并添加里面需要实现的方法,方法为required或optional都可以
接下来就是通知者,只要使用PostNotification宏,参数分别是协议、方法的SEL、方法调用(这里还会有XCode的提示输入)。
最后就是观察者,使用AddObserverWithProtocol添加自己需要观察的协议,并实现协议相关方法,如果是optional的方法,不实现也就不会接收到通知。释构时使用RemoveObserver移除通知。

XMCNotificationCenter不能完全替代NSNotificationCenter。因为系统很多行为是靠NSNotificationCenter通知出来的。但如果通知是由我们自己发出,都可以使用XMCNotificationCenter。实现原理也很简单,利用了宏展开的特性,用宏使得发送通知像调用函数一样方便。具体代码如下,代码量不多:(也可以到我的github上的XMCNotificationCenter看)

 

//
//  XMCNotificationCenter.h
//  XMCNotificationCenter
//
//  Created by xianmingchen on 16/7/5.
//  Copyright © 2016年 xianmingchen. All rights reserved.
//

#import <Foundation/Foundation.h>

//添加或删除监听
#define AddObserverWithProtocol(observer, observerProtocol) [[XMCNotificationCenter defaultCenter] addObserver:observer withProtocolKey:@protocol(observerProtocol)]
#define RemoveObserverWithProtocol(observer, observerProtocol) [[XMCNotificationCenter defaultCenter] removeObserver:observer withProtocolKey:@protocol(observerProtocol)]
#define RemoveObserver(observer) [[XMCNotificationCenter defaultCenter] removeObserver:observer];

//抛通知
#define PostNotification(observerProtocol, selector, func) \
{     NSArray *__observers__ = [[XMCNotificationCenter defaultCenter] observersWithProtocolKey:@protocol(observerProtocol)];    for (id observer in __observers__)     {         if ([observer respondsToSelector:selector])         {             [observer func];         }     } }

typedef Protocol *ObserverProtocolKey;
@interface XMCNotificationCenter : NSObject

+ (XMCNotificationCenter *)defaultCenter;

- (void)addObserver:(id)observer withProtocolKey:(ObserverProtocolKey)key;
- (void)removeObserver:(id)observer withProtocolKey:(ObserverProtocolKey)key;
- (void)removeObserver:(id)observer;
- (NSArray *)observersWithProtocolKey:(ObserverProtocolKey)key;
@end
/
//  XMCNotificationCenter.mm
//  XMCNotificationCenter
//
//  Created by xianmingchen on 16/7/5.
//  Copyright © 2016年 xianmingchen. All rights reserved.
//

#import "XMCNotificationCenter.h"


static CFRange fullRangeWithArray(CFArrayRef array);
static void ObserversCallbackFunc(const void *_key, const void *_value, void *context);

struct ObserverContext {
    __weak XMCNotificationCenter *center;
    __unsafe_unretained id observer;
};

@interface XMCNotificationCenter ()
{
    CFMutableDictionaryRef observersDictionary;
    dispatch_semaphore_t semaphore;
}
@end

@implementation XMCNotificationCenter
+ (XMCNotificationCenter *)defaultCenter
{
    static XMCNotificationCenter *center = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
       center = [[XMCNotificationCenter alloc] init];
    });
    
    return center;
}

- (id)init
{
    self = [super init];
    if (self) {
    
        CFDictionaryValueCallBacks kCallBack;
        kCallBack.version = 0;
        observersDictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
        semaphore = dispatch_semaphore_create(1);
    }
    return self;
}

#pragma mark - Add & Remove
- (void)addObserver:(id)observer withProtocolKey:(ObserverProtocolKey)key
{
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    
    if (![observer conformsToProtocol:key])
    {
    #ifdef DEBUG
        NSParameterAssert(@"observer not conformsToProtocol");
    #endif
        NSLog(@"client doesnot conforms to protocol: %@", NSStringFromProtocol(key));
    }

    CFStringRef cfStringKey =  (__bridge CFStringRef)NSStringFromProtocol(key);
    CFMutableArrayRef observersArray = (CFMutableArrayRef)CFDictionaryGetValue(observersDictionary, cfStringKey);
    if (observersArray == NULL)
    {
        observersArray = CFArrayCreateMutable(NULL, 0, NULL);
        CFDictionaryAddValue(observersDictionary, cfStringKey, (const void *)observersArray);
    }
    
    
    CFRange range = fullRangeWithArray(observersArray);
    
    BOOL isContains = CFArrayContainsValue(observersArray, range, (__bridge const void *)(observer));
    if (!isContains)
    {
        CFArrayAppendValue(observersArray, (__bridge const void *)observer);
    }
    
    dispatch_semaphore_signal(semaphore);
}

- (void)removeObserver:(id)observer withProtocolKey:(ObserverProtocolKey)key
{
    CFStringRef cfStringKey =  (__bridge CFStringRef)NSStringFromProtocol(key);
    [self p_removeObserver:observer withKey:cfStringKey];
}

- (void)p_removeObserver:(id)observer withKey:(CFStringRef)key
{
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    CFMutableArrayRef observersArray = (CFMutableArrayRef)CFDictionaryGetValue(observersDictionary, key);
    
    CFRange range = fullRangeWithArray(observersArray);
    
    CFIndex index = CFArrayGetFirstIndexOfValue(observersArray, range, (__bridge const void *)observer);
    if (index != -1)
    {
        CFArrayRemoveValueAtIndex(observersArray, index);
    }
    
    dispatch_semaphore_signal(semaphore);
}

- (void)removeObserver:(id)observer
{
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    ObserverContext context;
    context.center = self;
    context.observer = observer;
    CFDictionaryApplyFunction(observersDictionary, &ObserversCallbackFunc, &context);
    dispatch_semaphore_signal(semaphore);
}

#pragma mark - get
- (NSArray *)observersWithProtocolKey:(ObserverProtocolKey)key
{
    CFStringRef cfStringKey =  (__bridge CFStringRef)NSStringFromProtocol(key);
    CFArrayRef cfArray = (CFArrayRef)CFDictionaryGetValue(observersDictionary, cfStringKey);
    NSArray *array = (__bridge NSArray *)cfArray;
    
    return array;
}

@end
#pragma mark - other
static CFRange fullRangeWithArray(CFArrayRef array)
{
    CFRange range;
    if (array == NULL)
    {
        return range;
    }
    
    CFIndex length = CFArrayGetCount(array) - 1;
    if (length < 0) {
        length = 0;
    }
    range.location = 0;
    
    range.length = length;
    return range;
}

static void ObserversCallbackFunc(const void *_key, const void *_value, void *context) {
    if (!context || !_value || !_key)
    {
        return;
    }
    
    XMCNotificationCenter *center = ((ObserverContext *)context)->center;
    id observer = ((ObserverContext *)context)->observer;

    [center p_removeObserver:observer withKey:(CFStringRef)_key];
}

希望对大家有帮助。