ARC obliterated entire classes of bugs by automating memory management in acyclic contexts and providing zeroing weak references. Thanks to this, many classes no longer need to perform any cleanup during object destruction. The most common reason for dealloc these days? Notifications.
Broadcast messaging is vital to today's applications, but NSNotificationCenter has resisted modernization. Among its modern failings, its API enables fragile usage and it stores unsafe references to observers.
Karl and I were discussing the error-prone nature of APIs that require bracketed calls, like mutexes that conform to NSLocking1 and addObserver:selector:name:object:/removeObserver:name:object:. He posed the question: how do we get rid of bracketing APIs? To start with, how can we make NSNotificationCenter support weak observers?
The answer, of course, is a proxy whose lifetime is tied to the observer using object association:
The only API the proxy needs to provide is an initializer:
The implementation is pretty simple: the proxy adds and removes itself from the notification center in its own initialization methods, the target is stored weakly so in the time between target and proxy destruction the message is safely dispatched to nil, and the message forwarding machinery is minimal.
Lastly, a method in a category on NSNotificationCenter to tie it all together. Its primary responsibility is encapsulation, ensuring that the proxy's lifetime is tied as closely to the lifetime of the observer as possible:
- (void)nn_addWeakObserver:(id)observer selector:(SEL)selector name:(NSString *)name object:(id)sender;
This was simplified to fit in a blog post so it has a few limitations, such as the inability to remove the observation without destroying the observer itself, but it offers a glimpse into a future topic. Stay tuned!
edited on wednesday april 9th, 2014 at 13:33 (PDT):