How to use the Coordinator pattern in iOS

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

The trick here is properly defining the scope of the functionality of the view controllers that you use. Otherwise, for a flow of 4-5 screens, the size of your coordinators blow up as it micro-manages the controllers in the flow.

I’ve worked on a large application that used this pattern (almost exactly as he’s described it) and it’s amazing how easy it is to swap order of things, or add special case screens to the flow under certain circumstances.

As an alternative, I’d highly recommend reading and considering some of the points that Ben Sandofsky makes in his article, replacing “Coordinators” with simple View Controllers. https://sandofsky.com/blog/controller-hierarchies.html

Still, great thanks to Paul Hudson and Soroush Khanlou for introducing the Coordinator pattern and all of the talks/videos/literature and resulting discussion on the topic!

👍︎︎ 12 👤︎︎ u/redhand0421 📅︎︎ Jan 26 2019 🗫︎ replies

Took about 10 min to transform a small project over to use this. Love the organization of this, and it also pointed out some stuff I should probably refactor properly

👍︎︎ 5 👤︎︎ u/Sinbu 📅︎︎ Jan 26 2019 🗫︎ replies

You should credit the maker of this video /u/twostraws

👍︎︎ 11 👤︎︎ u/yar1vn 📅︎︎ Jan 26 2019 🗫︎ replies

Maybe it's because I'm a Mac developer and not an iOS developer but I'm not getting it.

What's the duplication that he claims to be removing here, exactly? I only see a little duplication being added: the Storyboard ID must always equal the class name. Also, I suppose, the protocol implementation essentially duplicates the protocol definition.

(Nit: why use a forced cast for the storyboard, and assume the ID was always set correctly, but not a force dereference in the controller? If for some reason the coordinator was released, all of the IBActions would silently become NOPs.)

The sample is a trivial app which would have been even simpler with ordinary segues. What's the case where you'd want the ability to easily re-wire the flow of your app? What would the "Buy" button ever do, if not present the BuyViewController? As a user, it seems to me that encouraging a simple top-to-bottom flow is a great benefit: apps are simple enough that I can understand them.

This strategy adds code and indirection, and makes the flow less visible. These have real costs, and while I'll grant that these are often worthwhile, I don't see what he's getting out of it. Is he just concerned that the controller was becoming too "massive", and he needed to move some of that code elsewhere? The compiler doesn't care, and it's easy to split a class across files, without having to completely restructure everything.

👍︎︎ 4 👤︎︎ u/applishish 📅︎︎ Jan 26 2019 🗫︎ replies

How does the coordinator make sure that it only instantiates a controller once? Does it check its child controllers to make sure it doesn’t exist in there?

👍︎︎ 3 👤︎︎ u/trypsin92 📅︎︎ Jan 26 2019 🗫︎ replies

Edit: All credits to /u/twostraws

👍︎︎ 1 👤︎︎ u/Marpo007 📅︎︎ Jan 27 2019 🗫︎ replies
Captions
[Music] hello I'm Paul Hudson and in this video we're going to look at implement in the coordinator pattern in iOS apps I'm gonna start by outlining what it is and what problem it solves walk you through the code then demonstrate a complete example with some live coding in Xcode if you find that sort of thing useful I have three tips for you first of course subscribe to my channel here on YouTube I have lots of other videos like this one second you should come to my weekly live coding streams Swift on Sundays we make full apps from scratch and more and third come to my site hacking with Swift comm I have well over a thousand articles and videos about Swift all three and most importantly updated the latest version of Swift ok let's start by looking at the problem we're facing when he first came to iOS development you will have met you I view controller this lies at the core of everything we do in iOS development but is a view or is it a controller at dot Swift 2018 Greg low tele a gave a great talk where he revealed the true secret behind the name UI view controller and it was staring us in the face the entire time this thing is a troll now there really a view or a controller and apples implementation of MVC isn't great they already set you off on the wrong foot you see Apple had to cram functionality into their view controllers which easily leads us towards spending we call massive view controllers or we cram functionality into those view controllers for example in Apple's default Xcode template for a master-detail interface the app delegate includes a correlator container and a split view controller delegate where its main view controller has modern logic manipulation core data code navigation table view delegation and data sources now people who add all that and more really shouldn't be allowed to complain about massive view controllers but of course that's easier said than done when it comes to deciding what should be in a view controller will find things like UI design our plating views with model data responding to user input saving her restoring state data sources and delegates animation networking navigation and more now some of these things we can get rid of fairly quickly your UI design that should go into a UI view subclass the same goes for your animation as for data sources and delegates they can easily be separate classes but that leaves navigation this is more complex than most people realize it's there to control the flow in your app so you just go from screen to screen B to screen C or to handle different variants for devices possibly also different variants for a B testing and most of this goes into UI view controller by default which is a real shame because that's already packed with functionality this is where coordinators come in they take over the control flow on your app they can handle the device variants and handle a be testing variants but they never replace a few controllers those things are still required so the solution I want to present to you for these problems and more is to use the coordinator pattern to replace this control flow in your view controllers with a separate object that does it really well and really cleanly this concept was introduced by Suroosh Connolly one of my favorite speakers in iOS and it starts with this line of code get written many times before navigation controller dot push through controller some do controller animated true this is a child which is up into its parent to tell it what to do and what we're seeing is view controller a has to know about create configure and display view controller be a different view controller which creates incredibly tight coupling this is doubly bad if using segues in interface builder because your flow is hard-coded you have no flexibility to rearrange or reuse them when you switch to coordinators that link between view controllers is broken view controller a has no knowledge of view controller be it doesn't care what's next if indeed anything is next you get true isolation instead you controller a speaks to its coordinator all it cares about is that it can post messages to its coordinator which can then take appropriate action and that coordinator is responsible for pushing and popping views in larger apps this coordinator is likely to be a protocol so you can replace the whole thing dynamically and get a different program flow best of all you can break up work into smaller chunks with sub coordinators handling one part of the user journey now given that we all agree tight coupling causes all sorts of problems I hope you can see why this approach is so incredible this takes three steps to do first we declare a coordinator protocol what it means to be a coordinator in our app we'll give an array of child coordinators if it's going to use them we'll give a navigation controller so it can push and pop views plus we'll give it a start method which is call Brits ready to take over control of the app second we create a concrete implementation of that protocol I'll create one here called main coordinator it has those two properties plus its start method which will create some sort of view controller assign itself to be the coordinator for that view controller so we can report back changes then push that to the navigation controller and finally in your view controllers when something happens you surfer that back to the coordinator for example without coordinators you might say I use a tap method create a view controller assign properties to it and present it with coordinators you don't really want any of that code inside your view controller you want to say hey coordinator please buy this thing and the coordinator will decide what that means and how that should actually take place and already doing here is moving one more thing out of view controllers but it brings us one step closer to solid code with a single responsibility principle the it responsible for one thing handling program flow even better rather than all parts your app needin to know how to get to a particular screen they all talk to your coordinator who knows how to buy no more repetition and so we stopped having a hard-coded viewcontroller flow in an app we can show any screen at any point freely we get true isolation between our view controllers they don't understand as a flow they don't care as a flow you can use them whenever you want to however you want to best of all these coordinators are all code or you control they aren't blue controllers so there's none of those UI view controller quirks who often fight with once you're up and running with coordinators you'll find the easy to use the only real speed bump is starting the app you see coordinators like to be there right at the start of your app so they can control the flow from the beginning it's not required but it's nice ok let's switch over to Xcode and do a code demo we're going to start by creating a new single view app project in Xcode I'll call this thing coordinators as I said first we need a coordinator protocol that all our coordinators will conform to so I'll create a new swift file called coordinator dot Swift inside there will import uikit declare a new protocol called coordinator VAR child coordinators isn't a rave coordinator get set and via navigation controller is a UI navigation controller get set and func start to make of your controllers easier to instantiate I usually add a storyboarded protocol that lets me create a view controllers from a storyboard so I'll create a new file called storyboard Swift import uikit and then make my protocol protocol storyboarded static func instantiate returns self well this means is whatever conforms this storyboard protocol will have an instantiate method on the type itself that when cold will return the type now I'm going to provide a default implementation of this by saying extension storyboarded where self is a uiviewcontroller static func instantiate returns self let ID equal string describing self that will say a string called uiviewcontroller for the class name uiviewcontroller and then let's storyboard equals UI storyboard name main bundle bundle main and finally return storyboard or instantiate view controller with identify ur ID force typecast as self now what this does is it allows us to create view controllers in a storyboard now the same storyboard ID as their class name these must match because when we call some view controller dot instantiate it will use the some view controller as a storyboard ID in main dot storyboard so it'll find out your controller in the storyboard put out instantiate it and typecast it and that's why the forced typecast is safe here because if you controller's class must always match its storyboard ID now we already have a view controller provided by Xcode 4 this default project so open view controller dot Swift and we'll make good form to storyboard now open main dot storyboard select the initial viewcontroller and give it the storyboard identifier viewcontroller next we decree our first coordinator something to start up the app so I'll create a new Swift file called main coordinator Swift in there I'll do import UIKit then class main coordinator conforms the coordinator give it its child coordinators array and its navigation controller and I'm making initializer that gives us a navigation controller so I'll say in it navigation controller is a UI navigation controller self that navigation controller equals navigation controller we have to add a start method - so I'll say funk start and now we can use that new storyboarded protocol so I'll say let VC equals view controller dot instantiate knavish patroller dot push view controller vc animated false now notice how this coordinator is not a view controller again we haven't got to file any of UI view controllers quirks here now that we have a coordinator we need to use that when our app starts so open the project settings and lick main for the main interface setting now open app delegate dot Swift and give it this property var coordinator is an optional main coordinator we're to create our window by hand now because previously that was done by our storyboard which you've now disabled so we're gonna modify that did finish launching with options method to create that window and also start our main coordinator so we'll say let nav controller equals UI navigation controller coordinator equals main coordinator navigation controller is our nav controller coordinator start after the window window equals UI window with a frame being UI screen main dot bounds window got root view controller equals our nav controller and window make key invisible we should be able to launch the app now and see something there we go it's not terribly interesting but it works so far we've only shown setup the main point of coordinators is to control program flow around your app so let's look at how that's done I'll start by creating two new UI view controller subclasses the first one I'll call by view controller and the second I'll call create account viewcontroller I want to make both of them conform to storyboarded so I'll do storyboarded here and here next I'll open Maine dot storyboard again and drag out to new view controllers is the first and here's a second for the first one I'll give it the class by viewcontroller and use that same name for its storyboard ID so our storyboard at protocol works and the second one I'll use create a camp view controller again for both the class and the storyboard ID so these are clearly visible on screen I'm going to add some labels to them so I'll drag out one label into the first view controller then get the title by as the second view controller I'll get another label drag that out and give this one a title create account now way to add two buttons to the first view controller so we can navigate to the other two so I'll drag out two buttons one called by and one called crate account we're going to connect those up to IB actions inside our main view controller so I'll switch to the assistant editor and create by tapped for the first button and create account tapped for the second button now all our viewcontroller way to talk to their coordinator like I said earlier for large apps you'll want to use protocols here but this is a fairly small app so we can refer to our main coordinator class directly so I'll add this property to all three view controllers week var coordinator optional main coordinator and again in by viewcontroller and again in create account viewcontroller now if you recall our main coordinator has a start method which bootstraps our app by creating our main view controller inside there I need to set the coordinator property to be self so that first view controller can call back to our coordinator correctly so I'll say VC coordinator equals self at this point we have three view controllers all being managed by a single coordinator but we still don't have a way to move between view controllers so the next step is to add two new methods to our main coordinator the first two by subscriptions and second to create accounts so I'll say func by subscription let VC equals by view controller Don instantiate VC the coordinator equals self and then navigation controller dot push view controller VC animated true the second method will do funk create account let VC equals create account view controllers on instantiate VC the coordinator equals self navigation controller dot push Wii controller vc animated true that's our coordinator code complete so the final step is to go back to the view controller class we had earlier and fill in those two IV action methods you made so I'll open the class I'll scroll down and find by taps and here I would say coordinator question mark dot by subscription and in Korea account tapped I'll say coordinator question mark dot create account and now when I run the app we should be able to navigate between screens freely I can press by to see the buy of your controller or go back and press create account to see the create account of your controller and now we have completed the functionality no view controllers know what comes next in the chain or how to configure it any view controller can trigger the purchase flow without known how it's done we can add centralized code to handle iPads and other layout variations plus we get true view controller isolation for more information on coordinators check out Suroosh car news blog conlou comm or see my own articles on coordinators at hacking Rousseff's comm and of course if you subscribe to my channel here on youtube I'll see you in the next video
Info
Channel: Paul Hudson
Views: 43,346
Rating: 4.942102 out of 5
Keywords: swift, coordinator, coordinators, pattern, ios, mvc, app, Xcode, design
Id: 7HgbcTqxoN4
Channel Id: undefined
Length: 18min 11sec (1091 seconds)
Published: Fri Jan 25 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.