NSNotificationCenter is Probably an Anti-Pattern
blog.jaredsinclair.com
blog.jaredsinclair.com
While I agree with the author that often delegates are a nicer pattern, I wouldn't go as far as calling NSNotificationCenter an anti-pattern. I also think that limiting its use to global notifications is not good advise.
My advise for using NSNotifications is whenever you want loose coupling between objects.
For example, I have an app that displays an iTunes-like status view at the top of the window. I don't want all the query objects and the status view tightly coupled. Instead, my query objects post notifications when the status changes, and the status view observes them. Using notifications lets me separate concerns, and avoid coupling between model and view layers.
Also, another powerful feature of NSNotifications is that an observer can decide on its own when it is no longer interested in notifications. When you have block-based completion handlers, there's usually no way to unregister a completion handler. This can lead to crashes as well, when a long-running request times out after the user has already closed the window.
[1]: There was a pretty severe bug in OS X 10.10 that caused views to be retained after their window was closed, so that many apps all of the sudden crashed when the views sent messages to their delegates which were deallocated. A workaround was to make sure to make sure that controllers call setDelegate:nil on their views in the dealloc method -- just like with NSNotificationCenter.
WindowServer: _CGXRemoveWindowFromWindowMovementGroup: window 0x1d is not attached to window 0x4d
My El Capitan installation is fresh. Didn't help. I think reading the logs in OS X since Yosemite, does make OS X feel buggy and it should probably not work as well as it does. :-/Delegate is probably the most fool proof way to do it and is pretty much protected by the compiler to give you the warnings you might need and doesn't require much template. But ultimately there are a lot of things where it's frankly a one to many scenario and delegation is out of the picture.
I suppose I've continually grappled fixing both bugs in KVO and NSNotification, and it seems like Notifications are much easier to find by just searching for the const string to audit the observers. KVO is tricker especially if there are keypaths and what if the name of the property is changed? The whole thing happens in the runtime so it's basically a nightmare.
So ultimately yeah, you can clean up KVO and make a better implementation. I've written something that makes a intermediary object that managed some of the trickier aspects of KVO (having to call super and pass a context and dealloc etc). But now I'm at a new place and I wouldn't put the effort into getting everyone on board into using that code instead of the usual Foundation stuff.
In many cases, directly-related pieces should probably have a tight understanding of what's happening with their neighbor or ancestor or descendant, and delegates are great for this. But sometimes, I want my software to announce that certain things have happened, or completed, or whatever, and not care who, if anyone, is listening, and NSNotificationCenter is brilliant for this. For instance, a top-level UI feature like an indeterminate progress indicator doesn't need to know of every single bit of work being performed by lower levels of the software, and tightly coupling them - even along a delegate chain of some sort - is fraught with potential edge cases. Simply listening for start and end announcements means dozens of not hundreds of lines of code eliminated, and maintaining a crazy delegate chain unnecessary.
In any case, I've found this pattern extremely helpful and useful, and is one of my favorite bits of working with Objective-C (and now Swift).
Edit: Sorry, just noticed your use of the qualifier "custom" there.
Once your codebase reaches a certain size, an event bus is a very powerful pattern that, if applied correctly, will keep your classes/functions/... decoupled.
Naturally, there is a huge potential for misuse, but that argument probably applies to any design pattern.