Lightweight Design Patterns in iOS (Part 2) - Presenter

Design Patterns are part of Mobile Development for a while now and a revolution towards Quality Assurance is on. Such patterns have become a standard among the community, yet implementing an academic one might come with a price β€” complexity.

Because some Design Patterns solve very complex problems, they often result in a complicated implementation as well. So complex sometimes, that we tend to use heavy Third Party Frameworks, even for simple use cases.

The time has come to combine quality and simplicity.

🎬 Hi there, I’m Jean!

Previously on the series Lightweight Design Patterns in iOS, we have covered the case of the Observer Pattern and how to make it feel like RxSwift! 😍
In this episode, we will take a quick look at the Presenter Pattern, the problems it solves as well as how to implement it in a simple and yet powerful manner! πŸ“Ί

Presenter Pattern


A Presenter is simply an independent layer of an architecture, which can show a View from anywhere in the application. πŸš€

In iOS, this means an independent class or struct able to present a ViewController on its own. πŸ‘Œ

The practical way


The practical way to present a ViewController is to have an extension on UIViewController to make use of the present(viewController:) method. πŸ’―

If we now look at an example, let’s say: present an Alert with an Error description, it would look pretty simple. πŸ‘

extension UIViewController {
    
    func present(error: Error, animated: Bool, completion: (() -> Void)? = nil) {
        let alertController = UIAlertController(
            title: "Error",
            message: error.localizedDescription,
            preferredStyle: .alert
        )
        let alertAction = UIAlertAction(
            title: "Ok",
            style: .default
        )
        alertController.addAction(alertAction)

        present(alertController, animated: animated, completion: completion)
    }
}

Though it might seem elegant at first, it actually comes with a price: every single ViewController is now able to present an Alert with an Error description. 😲

Do we really want that? Or would we rather delegate this logic to an other independent layer? πŸ€”

You know where I’m going… πŸ˜‰

The Presenter way


Using a Presenter, we implement a separate entity responsible for presenting a View. This means for us, a struct! πŸš€

In the example of presenting an Error, we would implement an ErrorPresenter struct with the actual error as property and the present(in viewController:) function. βœ…

struct ErrorPresenter {
    let error: Error

    func present(in viewController: UIViewController, animated: Bool, completion: (() -> Void)? = nil) {
        let alertController = UIAlertController(
            title: "Error",
            message: error.localizedDescription,
            preferredStyle: .alert
        )
        let alertAction = UIAlertAction(
            title: "Ok",
            style: .default
        )
        alertController.addAction(alertAction)

        viewController.present(alertController, animated: animated, completion: completion)
    }
}

And that’s all, we now have a completely independent Presenter, that can be called from anywhere in our App! πŸ‘

Calling our ErrorPresenter is as simple as it is elegant! 😎

let presenter = ErrorPresenter(error: NetworkError())
presenter.present(in: self, animated: true)

And boom! πŸ’₯
We just made a lightweight Presenter! πŸŽ‰

Worth it? Did that help you see what problems the Presenter Pattern is trying to solve? How to make such a pattern lightweight?

If so, follow me on Twitter, I’ll be happy to answer any of your questions and you’ll be the first one to know when a new article comes out! πŸ‘Œ

See you next week, for the Part 3 of my series Lightweight Design Patterns in iOS!

Bye bye! πŸ‘‹