Why you should stop using NotificationCenter and start using TopicEventBus

What is an EventBus?

EventBus is a way of distributing events within your app between a publisher and a subscriber, without the two parts knowing about each other.

Isn’t EventBus the same as NSNotificationCenter?

Yes, they sound the same, but in reality, NSNotificiationCenter suffers from some terrible issues:

1. Events are strings, and strings are not type-safe, some programmers may refer to them as “magic strings.”

It can get really messy since every typo affects functionality.
So you are probably using some CONST file defining all possible event names, well done!
But, you are not forcing anyone to use that file; meaning, a new programmer can come along and decide to fire a random new string defined in code.

2. When firing events using NSNotificationsCenter you probably noticed that objects fired are of type “id,” meaning no type, meaning no one knows what object they will get from listening to your event.

3. Say you want to observe event “user changed”, but you only care about a user with id “1234”. 
Wouldn’t it be nice if you could define a key you are interested in instead of listening to all “user changed” events and checking to see if the id matches the one you care about? Well, TopicEventBus can do that for you.

Show me the code! And tell me what’s in it for me.

Let’s build a chat app!

In this app, we are going to have multiple conversation screens; each one of them would like to know only about changes to its conversation.
The first step is to create an event for the conversation update:

class ConversationChangedEvent: TopicEvent {
let newTitle: String
init(conversationId: String, newTitle: String) {
self.newTitle = newTitle
super.init()
self.key = conversationId
}
}

Every event must inherit from “TopicEvent”, and in case it has a topic (in our example it will be the conversation id) set “key” property to the correct value.

Now, inside ConversationVC, subscribe to this event:
Notice you only need to specify the return value you are expecting for TopicEventBus to figure out the event you are subscribing for.

class ConversationVC: UIViewController {
let topicEventBus: TopicEventBus
let conversationId = "1234"

init(topicEventBus: TopicEventBus) {
self.topicEventBus = topicEventBus
}

override func viewDidLoad() {
super.viewDidLoad()
_ = self.topicEventBus.subscribe(topic: conversationId, callback: { (conversationChangedEvent: ConversationChangedEvent) in
// This will run every time "ConversationChangedEvent"
// with id 1234 will be fired.
})
}
}

This is how you fire an event:

class FiringService {
let topicEventBus: TopicEventBus
init(topicEventBus: TopicEventBus) {
self.topicEventBus = topicEventBus
}

func conversationTitleChanged() {
self.topicEventBus.fire(event: ConversationChangedEvent.init(conversationId: "1234",
newTitle: "First update"))
}
}

You did it! You fired your first event with topic. 🤗 🎉

TopicEventBus