Events

Coordinate implements an Events mechanism whose Events are nothing more than enums defined in a struct.

Events can be emitted by any subclass of UIResponder (like UIViewController and UIView) and Coordinators and can be intercepted by their ancestor, whether it is the immediate parentCoordinator or another Coordinator further above in the navigation flow.

This is the Events propagation chart in a Coordinator - UIViewController chain

Coordinate Events Diagram

So how to use Events?

Here is an example of usage

Definition

First you have to define it as an enum inside a global struct for scoping purposes, as in

struct AppEvents {
    ...

    enum Teams: CoordinateEvents, Equatable {
        ...
        case setFavorite(_ team: Team)
        ...
    }

}

Its a good practice to separate your Events in domains and use a naming that is clear to understand

The enum must conform to CoordinateEvents and Equatable protocols

Emission

Then you have to emit it, in this case inside a callback to a @IBAction

@objc func favoriteButtonTapped(_ sender: UIButton) {
    guard let team = self.team else { return }

    emitEvent(AppEvents.Teams.setFavorite(team))
    ...
}

The rootViewController of a Coordinator must conform to Coordinated protocol. More on that bellow

and Interception

Once emitted, an event will bubble up the Coordinator - UIViewController chain, where it can be intercepted at any point

Here it is intercepted inside a Coordinator

override func interceptEvent(_ event: CoordinateEvents) -> Bool {

    if let event = event as? AppEvents.Teams {
        if case .setFavorite(let team) = event {
            dependencies?.dataManager.setFavorite(team: team)
        }
    }
    ...
    return false
}

And then at another Coordinator higher on the hierarchy

override func interceptEvent(_ event: CoordinateEvents) -> Bool {

    if let event = event as? AppEvents.Teams {

        switch event {
        case .setFavorite:
            self.updateProfileTabIcon()
            return true
        ...
        }

    }
    ...    
}

To intercept an event, just override func interceptEvent(_ event: CoordinateEvents) -> Bool and react to the specific event you want.

If you return true on this method, the event will stop bubbling up

With this mechanism in place, we can send messages up on the hierarchy and intercept them wherever we need it, without the need of using Delegates or other mechanisms, that have their limitations outlined here

Found errors? Think you can improve this documentation? Simply click the Edit link at the top of the page, and then the icon on Github to make your changes.