Dealing with NotificationCenter is daily task for all iOS developers. Either it’s a system notification such as KeyboardShow/KeyboardHide or CustomNotification to post some information app wide, we all have used Notifications.
Yeah, So. Do you have something interesting to say?
Well, answer to that question is, Yes. Today, we are gonna discuss notification programming in such a way, that it will become as easy as eating an apple pie. (I don’t think anyone can deny it, eating an apple pie is just so satisfying, obviously if you love apple pie in first place ;p )
Old way of handling notification
In Swift we focus on writing all the APIs in strongly typed manner, then why not same with Notifications? Let’s see an example of default way of doing notification handling.
We write this same code again and again or we create a
BaseViewController and have these defined or maybe a
UIViewController extension. But all of these are still not efficient as you have to dig into
notification.userInfo dictionary to get relevant information.
(Sorry, about the art being not so good. Tried to do my best. ;))
We want to define notifications in such a way, where we can definitively get the data from our notification observer (strongly typed), not a userInfo dictionary. This way we will enforce swift type system to help us writing type safe and bug free code. In this process we will also redefine how we observe our notification to make our code
DRY(don’t repeat yourself).
To create typed notification we can first define an
NotificationDescriptor struct. Our
NotificationDescriptor will have two properties,
namedefining unique notification name
convertclosure, which help us extract out data from Notification.userInfo
With help of Swift’s Generic type we can use above Struct for all type of notifications and describe our notifications using this.
Next we can extend
NotificationCenter to provide us a convenience method over default
But there is one thing missing in above implementation. We have added the observer but we are ignoring the token received from
addObserver method. Without this token we won’t be able to deregister the notification. For this purpose we can define a
And redefine our
addObserver method this way:-
We can store the
Token returned by above function as a ViewController property, when ViewController’s
deinit gets called,
Token will also gets destroyed and notification gets deregistered.
How to use it
We will define KeyboardShow and KeyboardHide notification using our
Let’s define a struct with info we require from keyboard notification using KeyboardNotificationKeys.
We can also define an initializer to our
KeyboardData which take notification and instantiate
KeyboardData. This can be used as our convert function and we don’t have to redefine convert for KeyboardShow and KeyboardHide.
This is also the most important part of our
Type-Safe Notification. We will have strictly defined data in our application and all the parsing logic is separated out for easy debugging and testing.
KeyboardHideDescriptor will become
We have also encapsulated these properties in
SystemNotification struct, so that our global namespace doesn’t get polluted with all different types of notification descriptors.
Having different notification with respective descriptor defined at a central place, using these in a UIViewController is very simple and we don’t have to track the notification for deregister.
This way we are also freeing up our UIViewController from other logic and only allowing it to handle views. This is also highly reusable, all the repetitive code is moved to a single place and this makes our code
For MVVM architecture above implementation fits perfect, a viewController should only handle view related logic only.
Above pattern is inspired from SwiftTalk Objc.io. I would highly recommend watching this episode. They also define a different pattern using Protocol for handling the Notification. But for our use case we are fine with above implementation, much simpler and easy to use.
The moldedbits Team