The CocoaTouch UI framework has its own built-in implementation of the Mediator design pattern, named NSNotificationCenter. You can use an instance of the NSNotificationCenter class to broadcast notifications to any objects that are interested in that particular event. Several components in CocoaTouch use this mechanism, such as how MPMoviePlayerController sends out notifications when a movie starts and stops.
To a .NET developer this might seem like a strange and inconvenient way to raise and handle an event on an object. In one sense, that is true. Since Objective-C does not have first-class support for constrained multicast delegates (i.e. events) like most .NET languages, you can instead use NSNotificationCenter to publish something to other entities, pass related arguments, and a include back pointer to the object that published the notification. Sounds like events, right?
To a certain extent that is true. However, NSNotificationCenter is not a substitute for events. It is an implementation of the Mediator design pattern, much like the Messenger class in my MVVM Foundation library (used by WPF developers). It provides an externalized event source, which helps reduce coupling between publisher objects and subscriber objects.
The difference between .NET events and a Mediator, regardless of the platform, is that an event can only be raised by the object that owns the event. This requires all subscribers to reference the event publisher object, thus increasing the system’s self-awareness. I don’t mean to imply that .NET events are a bad thing, but in some situations simpler designs can be achieved by using a third party to broker events between parties.
Enough pontification, now let’s look at an example of using this cool class. First let’s declare the name of a custom notification and the name of the dictionary entry that stores the ‘message’ argument passed to the notification recipients.
Now we will head over to the implementation file and define those values…
Obviously the value of those strings don’t matter, so long as they’re unique within the scope of my application. Technically it is not necessary to take the extra step of defining these string identifiers in a separate file, you could just hard-code the values into your methods, repeating the values wherever needed. But that would make the person who maintains your code want to viciously murder you in your sleep.
Next let’s see how to send out a notification using NSNotificationCenter.
Last but not least, the subscriber code.
That’s all for this post.
I think that .NET events is the most misused mechanism in .NET
events should be used for UI purposes, and not for communication between components and modules.
Because of this misconception in .NET, events are the #1 reason for memory leaks.
Events are very hard to manage and maintain and unless the author of the class removes the registration on a specific event, there’s a memory leak.
Using an event broker/mediator pattern offers a much more cleaner and manageable design, and it seems like Objective C has it right and MS has it wrong this time.
I agree that .NET events are a major cause of memory leaks. However, with NSNotificationCenter the responsibility of removing your notification observer still exists. Since NSNotificationCenter does not retain its observers (in a reference counting / memory management sense) it is possible for it to reference a deallocated object. If it were to send a message to a deallocated observer object, a runtime error will occur.
The moral of the story is, sending generic notifications between objects, regardless of the platform, has pitfalls unless one is diligent about cleaning up after oneself. With that being said, I think that the problem of having a runtime error thrown is usually easier to debug than a memory leak.
I agree, but as I see it, the main issue is that if the notifications are managed in on place (i.e. event broker), the framework can handle the resource issues from a centralized place, as opposed to the events system where the registration/un-registration is scattered between the the different objects.
I’m working with WPF and SL using MVVM in my everyday work, even your libraries Josh 🙂 , and I have recently started working with Objective-C developing for the iPhone during my free time. It was a very nice surprise when I started working with Objective-C to find this is way “events” was done in Objective-C (or in the library that is). We are devloping games using the MVC patterns and my prior knowledge about MVVM + Messenger made it really easy/clear about how to use this! During my work with .NET i have also learned the painful way that .NET events cause so many memory leaks. The strange thing is that there are so many developers out there that does not know this. Maybe the “forced control” with retain/release is better than GC sometimes (but also a real hassle i must admit).
A last tip about messages (no mather if it’s WPF or objective-c). I always categorize my messages as “Requests” or “Notifications”. A request message is sent when I want a part of the program to tell a different part of the program to do something, for example change a state, variable etc.
A notification message is sent when a part of the program want to tell other parts (other view models or models) that something has happened. For example it got a request message to change a state, it changed the state, it then sends a notification message about what was done.
That way the message flow get’s alot easier to understand and you avoid endless cycles of messages causing stack overflows etc.
Just a friendly tip from me 🙂
Great feedback, Johan. Thanks!
I definitely like your Request/Notification taxonomy for messages. That makes a lot of sense.
I wonder why some Objective-C books categorize NSNotificationCenter as being an implementation of the observer pattern rather than mediator….as I recall one of them is Cocoa Design Patterns, but I’m not sure exactly. I agree that it’s a mediator implementation…
Hi, very nice article(s). However I agree with what you are writing about NSNotification, it is not an Mediator pattern, it is an Observer.
F.e (NS)(My)Controllers comunicating with other controllers are defined as Mediators.