iosobjective-cnsdictionarynsnotificationcenternsnotification

Object parameter in method postNotification of NSNotificationCenter


In my iOS application, I am posting a NSNotification and catching it in one of my UIView in main thread. I want to pass extra information along with the notification. I was using userInfo dictionary of NSNotification for that.

[[NSNotificationCenter defaultCenter] postNotificationName:@"NotifyValueComputedFromJS" object:self userInfo:@{@"notificationKey":key,@"notificationValue":value,@"notificationColor":color,@"notificationTimeStamp":time}];

key, value, color and time are local variables which contains the value I need to pass. In UIView I am adding observer for this notification and I am using notification.userInfo to get these data

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification:) name:@"NotifyValueComputedFromJS" object:nil];

-(void)receiveNotification:(NSNotification *)notification
{
     if ([notification.userInfo valueForKey:@"notificationKey"]!=nil && [[notification.userInfo valueForKey:@"notificationKey"] isEqualToString:self.notificationKey] && [notification.userInfo valueForKey:@"notificationValue"]!=nil) {
         [self updateLabelWithValue:[notification.userInfo valueForKey:@"notificationValue"]];
     }
}

The frequency in which this notification is posted is 4 times in one second. I am doing some animations also in main thread. The problem I am facing here is my UI is lagging. UI will respond to scroll events or touch events with huge delay(I have faced a delay of even 1 to 2 seconds). After some research I came to know that NSDictionary is bulky and will cause lag if used in main thread. Is there any other way I can pass my data through NSNotification?

I have tried out another way. I have created a custom NSObject class to save the data I want and I am passing it as the object parameter of postNotification method.

[[NSNotificationCenter defaultCenter] postNotificationName:@"NotifyValueComputedFromJS" object:customDataObject userInfo:nil];

Here customDataObject is an instance of my custom NSObject class. I know the parameter is meant to be the sender of notification(usually it will be self). Is it a wrong approach if I am sending a custom object as parameter?


Solution

  • As BobDave mentioned, the key is to send the notification on some thread other than the main UI thread. This can be accomplished with dispatch_async, or with a queue.

    The typical pattern for this behavior is sender:

    -(void)sendDataToObserver {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [[NSNotificationCenter defaultCenter] postNotificationName:@"NotifyValueComputedFromJS" object:customDataObject userInfo:userInfo:@{@"notificationKey":key,@"notificationValue":value,@"notificationColor":color,@"notificationTimeStamp":time}];
        });
    }
    

    And receiver (NOTE: weak self because retain cycles):

    -(void)addObserver {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification:) name:@"NotifyValueComputedFromJS" object:nil];
    }
    
    -(void)receiveNotification:(NSNotification *)notification {
         if ([notification.userInfo valueForKey:@"notificationKey"]!=nil && [[notification.userInfo valueForKey:@"notificationKey"] isEqualToString:self.notificationKey] && [notification.userInfo valueForKey:@"notificationValue"]!=nil) {
             __weak typeof (self) weakSelf = self;
    
             dispatch_async(dispatch_get_main_queue(), ^{
                 [weakSelf updateLabelWithValue:[notification.userInfo valueForKey:@"notificationValue"]];
             });
         }
    }