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?
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"]];
});
}
}