如何实现NSNotificationCenter(块样式)?

时间:2016-05-18 19:43:52

标签: objective-c block nsnotificationcenter

这是一个面试问题。我知道如何使用NSDictionary实现非阻止通知中心。但是我不知道如何实现阻止NSNotification中心,因为没有"观察者"。这是代码。有什么想法吗?

#import <Foundation/Foundation.h>

/** LBNotificationCenter.h */

typedef void (^Observer)(NSString *name, id data);

@interface LBNotificationCenter : NSObject

- (void)addObserverForName:(NSString *)name block:(Observer)block;
- (void)removeObserverForName:(NSString *)name block:(Observer)block;
- (void)postNotification:(NSString *)name data:(id)data;

@end

/** LBNotificationCenter.m */

@interface LBNotificationCenter ()

@end

@implementation LBNotificationCenter

- (instancetype)init 
{
    self = [super init];
    if (self) {

    }
    return self;
}

- (void)addObserverForName:(NSString *)name block:(Observer)block 
{
      //add your code here
}

- (void)removeObserverForName:(NSString *)name block:(Observer)block 
{
       //add your code here
}

- (void)postNotification:(NSString *)name data:(id)data 
{
    //add your code here
}

2 个答案:

答案 0 :(得分:3)

块是普通对象,因此您可以将它们存储在NSArray / NSDictionary中。说实现很简单。

#import <Foundation/Foundation.h>

/** LBNotificationCenter.h */

typedef void (^Observer)(NSString *name, id data);

@interface LBNotificationCenter : NSObject

- (void)addObserverForName:(NSString *)name block:(Observer)block;
- (void)removeObserverForName:(NSString *)name block:(Observer)block;
- (void)postNotification:(NSString *)name data:(id)data;

@end

/** LBNotificationCenter.m */

@interface LBNotificationCenter ()
@property (strong, nonatomic) NSMutableDictionary <id, NSMutableArray <Observer> *> *observers;
@end

@implementation LBNotificationCenter

- (instancetype)init
{
    self = [super init];
    if (self) {
        _observers = [NSMutableDictionary new];
    }
    return self;
}

- (void)addObserverForName:(NSString *)name block:(Observer)block
{
    // check name and block for presence...

    NSMutableArray *nameObservers = self.observers[name];

    if (nameObservers == nil) {
        nameObservers = (self.observers[name] = [NSMutableArray new]);
    }

    [nameObservers addObject:block];
}

- (void)removeObserverForName:(NSString *)name block:(Observer)block
{
    // check name and block for presence...

    NSMutableArray *nameObservers = self.observers[name];

    // Some people might argue that this check is not needed
    // as Objective-C allows messaging nil
    // I prefer to keep it explicit
    if (nameObservers == nil) {
        return;
    }

    [nameObservers removeObject:block];
}

- (void)postNotification:(NSString *)name data:(id)data
{
    // check name and data for presence...

    NSMutableArray *nameObservers = self.observers[name];

    if (nameObservers == nil) {
        return;
    }

    for (Observer observer in nameObservers) {
        observer(name, data);
    }
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSString *const Notification1 = @"Notification1";
        NSString *const Notification2 = @"Notification2";

        LBNotificationCenter *notificationCenter = [LBNotificationCenter new];

        Observer observer1 = ^(NSString *name, id data) {
            NSLog(@"Observer1 is called for name: %@ with some data: %@", name, data);
        };
        Observer observer2 = ^(NSString *name, id data) {
            NSLog(@"Observer2 is called for name: %@ with some data: %@", name, data);
        };

        [notificationCenter addObserverForName:Notification1 block:observer1];
        [notificationCenter addObserverForName:Notification2 block:observer2];

        [notificationCenter postNotification:Notification1 data:@"Some data"];
        [notificationCenter postNotification:Notification2 data:@"Some data"];

        [notificationCenter removeObserverForName:Notification1 block:observer1];

        // no observer is listening at this point so no logs for Notification1...
        [notificationCenter postNotification:Notification1 data:@"Some data"];

        [notificationCenter postNotification:Notification2 data:@"Some data"];
    }

    return 0;
}

答案 1 :(得分:0)

为什么不将这些块添加到NSDictionary?你可以像解释in this answer

那样做