Swift2Go
Published in

Swift2Go

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

a place where Swift Developers share knowledge.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Matan Cohen Abravanel

Matan Cohen Abravanel

The man who does not read has no advantage over the man who cannot read

More from Medium

How to center align cells in UICollectionViewCompositionalLayout

Resolve a question about pthread_rwlock_t

How the Fleksy SDK is distributed using the Swift Package Manager

👾 Apollo Integration Fun on iOS