mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-04 09:53:41 +00:00
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:
@@ -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 receiver’s 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];
|
||||
|
||||
Reference in New Issue
Block a user