Coalescing while using NSNotificationQueue

2019-06-08 15:20发布

问题:

I wrote the following code to perform coalescing using NSNotificationQueue.I want to post only one notification even if the event occurs multiple times.

- (void) test000AsyncTesting
{
    [NSRunLoop currentRunLoop];
    [[NSNotificationCenter defaultCenter] addObserver:self             selector:@selector(async000:) name:@"async000" object:self];
    [[NSNotificationQueue defaultQueue] enqueueNotification:[NSNotification notificationWithName:@"async000" object:self]
    postingStyle:NSPostWhenIdle coalesceMask:NSNotificationCoalescingOnName forModes:nil];

    while (i<2)
    {
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
        NSLog(@"Polling...");
        i++;
    }
}

- (void) async000:(NSNotification*)notification;
{
    NSLog(@"NSNotificationQueue");
}

Everytime on calling the method 'test000AsyncTesting',the notifications with same name are added to the queue. As per the concept of coalescing,if queue has any number of notifications but with same name then it will be posted only once. But when I run my code,'async000:'is called multiple times which is exactly equal to the number of notifications added to the NSNotificationQueue.I think the coalescing is not working.
For me, execution of code remains same in both of these cases:

Case 1: [[NSNotificationQueue defaultQueue] enqueueNotification:[NSNotification notificationWithName:@"async000" object:self] postingStyle:NSPostWhenIdle coalesceMask:NSNotificationCoalescingOnName forModes:nil];

Case 2: [[NSNotificationQueue defaultQueue] enqueueNotification: [NSNotification notificationWithName:@"async000" object:self] postingStyle:NSPostWhenIdle];

Please tell the error in my code.

回答1:

Coalescing only combines notifications that occur until control flow returns to the run loop. If you enqueue a notification on a subsequent trip through the run loop, that will result in a separate notification call.

To see this, change test000AsyncTesting to enqueue 2 notifications like this:

[[NSNotificationQueue defaultQueue] enqueueNotification:[NSNotification notificationWithName:@"async000" object:self]
postingStyle:NSPostWhenIdle coalesceMask:NSNotificationCoalescingOnName forModes:nil];

[[NSNotificationQueue defaultQueue] enqueueNotification:[NSNotification notificationWithName:@"async000" object:self]
postingStyle:NSPostWhenIdle coalesceMask:NSNotificationCoalescingOnName forModes:nil];

Then async000 will only be called once when it polls.

For testing, change the coalesceMask to be NSNotificationNoCoalescing then you will see 2 calls to async000 when polls.



回答2:

You must "Deregister" the notification; try this:

-(void)dealloc
{    
    [[NSNotificationCenter defaultCenter]removeObserver:self name:@"async000" object:nil];

    [super dealloc];
}