New: added method addObserverForName:object::usingBlock: in CPNotificationCenter

Previously, the method addObserverForName:object::usingBlock: didn't exist in Cappuccino.
Now it does.

To observe, you need to use the method - (id <CPObject>)addObserverForName:(CPString)aNotificationName object:(id)anObject usingBlock:(Function)block

To unregister observations, you pass the object returned by this method to removeObserver:. You must invoke removeObserver: or removeObserver:name:object:.

Test /Tests/Foundation/CPNotificationCenterTest.j

Fixed #2259
This commit is contained in:
Alexandre Wilhelm
2014-11-20 15:24:23 -08:00
parent d5b4d66272
commit fe25dbd872
2 changed files with 106 additions and 7 deletions
+61 -7
View File
@@ -68,7 +68,8 @@ var CPNotificationDefaultCenter = nil;
_namedRegistries = @{};
_unnamedRegistry = [[_CPNotificationRegistry alloc] init];
}
return self;
return self;
}
/*!
@@ -81,9 +82,35 @@ var CPNotificationDefaultCenter = nil;
*/
- (void)addObserver:(id)anObserver selector:(SEL)aSelector name:(CPString)aNotificationName object:(id)anObject
{
var registry,
var registry = [self _registryForNotificationName:aNotificationName],
observer = [[_CPNotificationObserver alloc] initWithObserver:anObserver selector:aSelector];
[registry addObserver:observer object:anObject];
}
/*!
Adds an entry to the receivers dispatch table with a block, and optional criteria: notification name and sender.
@param aNotificationName the name of the notification the observer wants to watch
@param anObject the object in the notification the observer wants to watch
@param block the block to be executed when the notification is received.
*/
- (id <CPObject>)addObserverForName:(CPString)aNotificationName object:(id)anObject usingBlock:(Function)block
{
var registry = [self _registryForNotificationName:aNotificationName],
observer = [[_CPNotificationObserver alloc] initWithBlock:block];
[registry addObserver:observer object:anObject];
return observer;
}
/*!
@ignore
*/
- (_CPNotificationRegistry)_registryForNotificationName:(CPString)aNotificationName
{
var registry;
if (aNotificationName == nil)
registry = _unnamedRegistry;
else if (!(registry = [_namedRegistries objectForKey:aNotificationName]))
@@ -92,7 +119,7 @@ var CPNotificationDefaultCenter = nil;
[_namedRegistries setObject:registry forKey:aNotificationName];
}
[registry addObserver:observer object:anObject];
return registry;
}
/*!
@@ -129,7 +156,10 @@ var CPNotificationDefaultCenter = nil;
[_unnamedRegistry removeObserver:anObserver object:anObject];
}
else
{
[[_namedRegistries objectForKey:aNotificationName] removeObserver:anObserver object:anObject];
}
}
/*!
@@ -233,7 +263,8 @@ var _CPNotificationCenterPostNotification = function(/* CPNotificationCenter */
observersEnumerator = [observers objectEnumerator];
while ((observer = [observersEnumerator nextObject]) !== nil)
if ([observer observer] == anObserver)
if ([observer observer] == anObserver ||
([observer block] && [anObserver respondsToSelector:@selector(block)] && [observer block] == [anObserver block]))
[observers removeObject:observer];
if (![observers count])
@@ -248,7 +279,8 @@ var _CPNotificationCenterPostNotification = function(/* CPNotificationCenter */
observersEnumerator = [observers objectEnumerator];
while ((observer = [observersEnumerator nextObject]) !== nil)
if ([observer observer] == anObserver)
if ([observer observer] == anObserver ||
([observer block] && [anObserver respondsToSelector:@selector(block)] && [observer block] == [anObserver block]))
[observers removeObject:observer];
if (![observers count])
@@ -312,8 +344,9 @@ var _CPNotificationCenterPostNotification = function(/* CPNotificationCenter */
/* @ignore */
@implementation _CPNotificationObserver : CPObject
{
id _observer;
SEL _selector;
id _observer;
Function _block;
SEL _selector;
}
- (id)initWithObserver:(id)anObserver selector:(SEL)aSelector
@@ -327,13 +360,34 @@ var _CPNotificationCenterPostNotification = function(/* CPNotificationCenter */
return self;
}
- (id)initWithBlock:(Function)aBlock
{
if (self)
{
_block = aBlock;
}
return self;
}
- (id)observer
{
return _observer;
}
- (id)block
{
return _block;
}
- (void)postNotification:(CPNotification)aNotification
{
if (_block)
{
_block(aNotification);
return;
}
[_observer performSelector:_selector withObject:aNotification];
}
@@ -52,6 +52,51 @@ var TestNotification = @"TestNotification";
[self assert:8 equals:notificationCount message:@"observer should not be notified"];
}
- (void)testNotifyWithBlocks
{
var center = [CPNotificationCenter defaultCenter];
notificationCount = 0;
var notificationBlock = function(notification){
notificationCount += 1;
};
var observer2 = [center addObserverForName:TestNotification object:2 usingBlock:notificationBlock],
observer25 = [center addObserverForName:TestNotification object:25 usingBlock:notificationBlock];
[center postNotificationName:TestNotification object:self];
[self assert:0 equals:notificationCount message:@"observer should only be notified for object '2'"];
[center postNotificationName:TestNotification object:2];
[self assert:1 equals:notificationCount message:@"observer should be notified for object '2'"];
var observerNil = [center addObserverForName:TestNotification object:nil usingBlock:notificationBlock];
[center postNotificationName:TestNotification object:2];
[self assert:3 equals:notificationCount message:@"observer should be notified for object '2' and for any object"];
[center removeObserver:observer2 name:TestNotification object:2];
[center postNotificationName:TestNotification object:2];
[self assert:4 equals:notificationCount message:@"observer should be notified only for any object"];
// At this point we have TestNofication:nil observer and a TestNotification:25 observer.
observer2 = [center addObserverForName:nil object:2 usingBlock:notificationBlock];
[center postNotificationName:TestNotification object:2];
[self assert:6 equals:notificationCount message:@"observer should be notified for TestNofication and for object '2' (TestNotification)"];
[center postNotificationName:@"RandomNotification" object:2];
[self assert:7 equals:notificationCount message:@"observer should be notified for object '2' (RandomNotification)"];
[center removeObserver:observer2];
[center removeObserver:observer25];
[center removeObserver:observerNil];
[center postNotificationName:TestNotification object:nil];
[center postNotificationName:TestNotification object:2];
[center postNotificationName:TestNotification object:25];
[self assert:7 equals:notificationCount message:@"observer should not be notified"];
}
- (void)testAddObserversDuringNotification
{
var center = [CPNotificationCenter defaultCenter];