addzo
addzo

Reputation: 867

Passing NSNotifications. Good? Bad? NBD?

I'm trying to think through the ramifications of passing an NSNotification object as a var to a method.

It seems like it's difficult to trace what happens to a the flow of logic with a notification anyway (without some great commenting and method/object naming) so passing the notification to another method/class/lib/project would just make it even less fun to debug or respond intelligently to an error.

But it just feels like it's the sort of thing that has a lot of hidden gotchas potentially.

And I know there are still a lot of people out there who love notifications.

So does anyone have some pros/cons/better-practices about passing the actual NSNotification object as a var between methods?

Just for clarity's sake here's some pseudo code:

[[NSNotificationCenter defaultCenter] postNotificationName:kSuperImportantNotification object:self userInfo:soMetaDict];

... Later in the code:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(importantThingHappened:) name:kSuperImportantNotification object:nil];

... Later in the code:

- (void) importantThingHappened:(NSNotification *)notification {
    [respondingInterestedClass executeSomethingWith:notification];
}

... In "respondingInterestedClass":

- (void)executeServicesDiscoveredBlock:(NSNotification *)notification {
    // ... do something with the NSNotificaiton object.
}

Thanks

Upvotes: 0

Views: 197

Answers (2)

Hazneliel
Hazneliel

Reputation: 541

It depends in what you are doing, usually this is when to use what:

  • One-to-One relationship and loose coupling: Delegate
  • One-to-One relationship and tight coupling: Direct method calls
  • One-to-Many relationship and loose coupling: Notifications
  • One-to-Many relationship and tight coupling: KVO

So you should not use Notifications for all kind of communication, lot of developers use them heavily even when its not needed.

Saying this, it is totally fine to pass the notification object to the method handler, but don't pass it anywhere else.

Upvotes: 4

bbum
bbum

Reputation: 162712

Putting aside how and when notifications should be used and focusing purely on the ephemeral set of uses that are totally the right choice....

Once received, the notification object is a state container that contains some set of state in a format that is convenient to the system. You can shoehorn whatever you want into it by shoving key/value pairs into a dictionary and passing it as the userInfo, if you want, but it is still the system state.

In a well designed body of code, there are hard fought barriers through which the format of the data and the encapsulated messaging are well defined. In a Model-View-Controller system, for example, a Model class won't be a subclass of UIView or handle user events directly.

And Notifications should be treated the same. When the notification is received, unwrap it into whatever internal-and-specific-to-your-architecture representation you want and pass that around.

Or, consider:

- (void) somethingChangedNotification:(NSNotification *)changed
{
    [myModelGoop applyChange:...];
}

@implementation MyModelLayer
- (void)applyChange:(....)change
{
}

In the above, you could certainly pass the notification object into the model layer. But that's just pushing a system specific implementation detail into your model.

What happens the moment you have changes that aren't triggered via an NSNotification? Your either left to encapsulate your change into a fake NSNotification instance (because posting a notification may have side effects depending on who is observing) or you have to refactor the above to no longer take a notification in the model layer.

Better to get rid of the dependencies on system encapsulation early.

To that end, the NSNotification instance should never be passed out of the method that handles the notification.

Upvotes: 2

Related Questions