From 3e29732e462e02dacfd66851e6dd67886ed69889 Mon Sep 17 00:00:00 2001 From: Alexandre Wilhelm Date: Thu, 8 Oct 2015 11:23:07 -0700 Subject: [PATCH] Fixed: OperationQueue for the CPNotificationCenter is not ignored anymore Previously, the operationQueue given to the notificationCenter was ignored. Tests in CPNotificationCenterTest.j --- Foundation/CPNotificationCenter.j | 59 ++++++++++++++++++--- Tests/Foundation/CPNotificationCenterTest.j | 51 ++++++++++++++++++ 2 files changed, 102 insertions(+), 8 deletions(-) diff --git a/Foundation/CPNotificationCenter.j b/Foundation/CPNotificationCenter.j index f06c22b0a..5f8ff94da 100644 --- a/Foundation/CPNotificationCenter.j +++ b/Foundation/CPNotificationCenter.j @@ -25,6 +25,8 @@ @import "CPException.j" @import "CPNotification.j" @import "CPNull.j" +@import "CPOperationQueue.j" +@import "CPOperation.j" @import "CPSet.j" @class _CPNotificationRegistry @@ -94,13 +96,13 @@ var CPNotificationDefaultCenter = nil; 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 queue is ignored for the moment + @param The operation queue to which block should be added. If you pass nil, the block is run synchronously on the posting thread. @param block the block to be executed when the notification is received. */ -- (id )addObserverForName:(CPString)aNotificationName object:(id)anObject queue:(id)queue usingBlock:(Function)block +- (id )addObserverForName:(CPString)aNotificationName object:(id)anObject queue:(CPOperationQueue)queue usingBlock:(Function)block { var registry = [self _registryForNotificationName:aNotificationName], - observer = [[_CPNotificationObserver alloc] initWithBlock:block]; + observer = [[_CPNotificationObserver alloc] initWithBlock:block queue:queue]; [registry addObserver:observer object:anObject]; @@ -344,9 +346,10 @@ var _CPNotificationCenterPostNotification = function(/* CPNotificationCenter */ /* @ignore */ @implementation _CPNotificationObserver : CPObject { - id _observer; - Function _block; - SEL _selector; + CPOperationQueue _operationQueue; + id _observer; + Function _block; + SEL _selector; } - (id)initWithObserver:(id)anObserver selector:(SEL)aSelector @@ -360,11 +363,12 @@ var _CPNotificationCenterPostNotification = function(/* CPNotificationCenter */ return self; } -- (id)initWithBlock:(Function)aBlock +- (id)initWithBlock:(Function)aBlock queue:(CPOperationQueue)aQueue { if (self) { _block = aBlock; + _operationQueue = aQueue; } return self; @@ -384,7 +388,11 @@ var _CPNotificationCenterPostNotification = function(/* CPNotificationCenter */ { if (_block) { - _block(aNotification); + if (!_operationQueue) + _block(aNotification); + else + [_operationQueue addOperation:[[_CPNotificationObserverOperation alloc] initWithBlock:_block notification:aNotification]]; + return; } @@ -392,3 +400,38 @@ var _CPNotificationCenterPostNotification = function(/* CPNotificationCenter */ } @end + +/* @ignore */ +@implementation _CPNotificationObserverOperation : CPOperation +{ + CPNotification _notification; + Function _block; +} + +/* @ignore */ +- (id)initWithBlock:(Function)aBlock notification:(CPNotification)aNotification +{ + self = [super init]; + + if (self) + { + _block = aBlock; + _notification = aNotification; + } + + return self; +} + +/* @ignore */ +- (void)main +{ + _block(_notification); +} + +/* @ignore */ +- (BOOL)isReady +{ + return YES; +} + +@end diff --git a/Tests/Foundation/CPNotificationCenterTest.j b/Tests/Foundation/CPNotificationCenterTest.j index 47aab1e0f..9695ac810 100644 --- a/Tests/Foundation/CPNotificationCenterTest.j +++ b/Tests/Foundation/CPNotificationCenterTest.j @@ -97,6 +97,57 @@ var TestNotification = @"TestNotification"; [self assert:7 equals:notificationCount message:@"observer should not be notified"]; } +- (void)testNotifyWithBlocksAndOperationQueue +{ + var center = [CPNotificationCenter defaultCenter], + queue = [[CPOperationQueue alloc] init]; + + notificationCount = 0; + + var notificationBlock = function(notification){ + notificationCount += 1; + }; + + var observer2 = [center addObserverForName:TestNotification object:2 queue:queue usingBlock:notificationBlock], + observer25 = [center addObserverForName:TestNotification object:25 queue:queue usingBlock:notificationBlock]; + + [center postNotificationName:TestNotification object:self]; + [center postNotificationName:TestNotification object:2]; + + [queue waitUntilAllOperationsAreFinished]; + [self assert:1 equals:notificationCount message:@"observer should be notified for object '2'"]; + + var observerNil = [center addObserverForName:TestNotification object:nil queue:queue usingBlock:notificationBlock]; + + [center postNotificationName:TestNotification object:2]; + [queue waitUntilAllOperationsAreFinished]; + [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]; + [queue waitUntilAllOperationsAreFinished]; + [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 queue:queue usingBlock:notificationBlock]; + + [center postNotificationName:TestNotification object:2]; + [queue waitUntilAllOperationsAreFinished]; + [self assert:6 equals:notificationCount message:@"observer should be notified for TestNofication and for object '2' (TestNotification)"]; + [center postNotificationName:@"RandomNotification" object:2]; + [queue waitUntilAllOperationsAreFinished]; + [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]; + [queue waitUntilAllOperationsAreFinished]; + [self assert:7 equals:notificationCount message:@"observer should not be notified"]; +} + - (void)testAddObserversDuringNotification { var center = [CPNotificationCenter defaultCenter];