Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
mikeash committed Jul 6, 2011
0 parents commit 7e5ff6a
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1 @@
a.out
15 changes: 15 additions & 0 deletions MANotificationCenter.h
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,15 @@

#import <Foundation/Foundation.h>


@interface MANotificationCenter : NSObject
{
CFMutableDictionaryRef _objectsDict;
}

- (id)addObserverForName: (NSString *)name object: (id)object block: (void (^)(NSNotification *note))block;
- (void)removeObserver: (id)observer;

- (void)postNotification: (NSNotification *)note;

@end
74 changes: 74 additions & 0 deletions MANotificationCenter.m
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,74 @@

#import "MANotificationCenter.h"


@implementation MANotificationCenter

- (id)init
{
if((self = [super init]))
{
_objectsDict = CFDictionaryCreateMutable(NULL, 0, NULL, &kCFTypeDictionaryValueCallBacks);
}
return self;
}

- (void)dealloc
{
CFRelease(_objectsDict);
[super dealloc];
}

- (id)addObserverForName: (NSString *)name object: (id)object block: (void (^)(NSNotification *note))block
{
NSMutableDictionary *innerDict = (id)CFDictionaryGetValue(_objectsDict, object);
if(!innerDict)
{
innerDict = [NSMutableDictionary dictionary];
CFDictionarySetValue(_objectsDict, object, innerDict);
}

NSMutableSet *observerBlocks = [innerDict objectForKey: name];
if(!observerBlocks)
{
observerBlocks = [NSMutableSet set];
[innerDict setObject: observerBlocks forKey: name];
}

void (^copiedBlock)(NSNotification *note);
copiedBlock = [block copy];

[observerBlocks addObject: copiedBlock];

[copiedBlock release];

__block id weakObject = object;
void (^removalBlock)(void) = ^{
NSMutableDictionary *innerDict = (id)CFDictionaryGetValue(_objectsDict, weakObject);
NSMutableSet *observerBlocks = [innerDict objectForKey: name];
[observerBlocks removeObject: copiedBlock];
if([observerBlocks count] == 0)
[innerDict removeObjectForKey: name];
if([innerDict count] == 0)
CFDictionaryRemoveValue(_objectsDict, weakObject);
};

return [[removalBlock copy] autorelease];
}

- (void)removeObserver: (id)observer
{
void (^removalBlock)(void) = observer;
removalBlock();
}

- (void)postNotification: (NSNotification *)note
{
NSDictionary *innerDict = (id)CFDictionaryGetValue(_objectsDict, [note object]);
NSSet *observerBlocks = [innerDict objectForKey: [note name]];
for(void (^block)(NSNotification *) in observerBlocks)
block(note);
}

@end

29 changes: 29 additions & 0 deletions main.m
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,29 @@
// gcc -framework Foundation main.m MANotificationCenter.m

#import "MANotificationCenter.h"


int main(int argc, char **argv)
{
[NSAutoreleasePool new];

MANotificationCenter *center = [[MANotificationCenter alloc] init];

id obj = [[NSObject alloc] init];
id otherObj = [[NSObject alloc] init];
[center addObserverForName: @"name" object: obj block: ^(NSNotification *note) {
NSLog(@"First block got notification %@", note);
}];
[center addObserverForName: @"name" object: obj block: ^(NSNotification *note) {
NSLog(@"Second block got notification %@", note);
}];
[center addObserverForName: @"othername" object: obj block: ^(NSNotification *note) {
NSLog(@"Third block got notification %@", note);
}];
[center addObserverForName: @"name" object: otherObj block: ^(NSNotification *note) {
NSLog(@"Fourth block got notification %@", note);
}];

[center postNotification: [NSNotification notificationWithName: @"name" object: obj]];
}

0 comments on commit 7e5ff6a

Please sign in to comment.