Coordinator: a Swift implementation of the Coordinator pattern for UIKit
Implementation of Coordinators app design pattern.
At a glance
- What is it?
- Coordinator is a small Swift package that implements the Coordinator design pattern for UIKit applications, with a folder you can drag into a project or a Swift Package Manager dependency. Version 8 moves to the Swift 6 language mode with strict concurrency enabled, which is a migration worth reading before you adopt it.
- Who is it for?
- Coordinator suits an iOS team whose screens have outgrown a view controller that both presents and owns navigation, since the pattern moves that responsibility into an object the caller holds, and the 8.x line is a reasonable target for a new Swift 6 codebase.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 140 days ago.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A pattern for the part of an app that presents screens
The README makes a strong claim about what this is. Coordinator is an implementation of the Coordinator design pattern, described as the application architecture pattern for iOS, carefully designed to fit into UIKit, so much that it could easily become a UICoordinator. The topic list places it in architecture, design-patterns, ios-lib and swift, which tells you the category it is meant to occupy. What the pattern actually solves is the well-known tangle in UIKit applications where a view controller that presents a screen also needs to know how to dismiss it, and where the second presenter ends up depending on the first one. Moving that coordination into its own object, which the presenting controller holds and calls, breaks the dependency. What this repository supplies is that object, written in Swift, for UIKit, and the README is candid that the pattern itself is not something you can pick up in one or two clever lines of code. Its advice is to give it a day or two, analyse it and play around with it.
Two ways to install, with different consequences
Installation is deliberately low friction, and the README offers two options. The first is to drag the Coordinator folder into your project, and the note is that it is only a handful of files. The second is to add the repository URL through Swift Package Manager, and the package ships a Package.swift at the root of the repository for exactly that. The difference between these two routes matters more than it looks. A dragged folder is source code inside your repository, so you can read it, modify it and step through it in the debugger, and it never conflicts with another package that happens to provide a type called Coordinator because the types end up in your own module. A package manager dependency is versioned, upgradeable and immutable in practice, which is what you want if you intend to follow the library's own changes over time. The README also points at a documentation directory in the repository with four separate documents, the Pattern, the Library, the Class and a recommended Implementation guide, which is where the day or two of reading is meant to happen.
Version 8 changes what strict concurrency means for you
The installation section doubles as a version history, and it is worth reading closely because the concurrency story is where the friction is. Version 8.x is using the Swift 6 language mode and has strict concurrency turned on. Version 7.x and up is made with Swift 5.5 concurrency in mind, which is to say async and await. Versions before that, the 6.x line, use closures. The releases visible here are 8.3 on 2026-07-09, 8.2 and 8.1 both on 2026-04-25, and the last push to the repository was on 2026-06-05. For a team still on Swift 5, adopting the 8.x line means adopting the Swift 6 language mode, and the migration note in the README confirms the shape of the change. Strict concurrency under Swift 6 turns data-race diagnostics into compile errors, so a Coordinator subclass that stores mutable state will need to be annotated and, in all likelihood, isolated to an actor or the main actor. That is the intended direction rather than a defect, but it is a change in the cost of using the library, not just a version number.
What changed in 8.1.0, in the author's own terms
The README documents the 8.1.0 migration explicitly, which is a good sign for a library you are going to depend on. Coordinator.init(rootViewController:) now takes a non-optional T instead of T?, and the reasoning is given: the previous signature crashed on nil through a preconditionFailure, so the only callers affected are those passing an explicit nil, which would have crashed anyway. Subclasses that construct their own root view controller should build it before calling super.init(rootViewController:). Second, CoordinatingQueuedMessage is now marked @MainActor () -> Void, and the note is that closures passed to enqueueMessage(_:) already had to run on the main actor in practice, so the annotation makes an existing contract explicit rather than adding a new restriction. Third, NavigationCoordinator now offers async overloads of present(_:animated:) and dismiss(animated:) alongside the existing completion-based methods, and these are described as purely additive, with existing call sites continuing to work while callers using structured concurrency can write await coord.present(vc) instead of wrapping UIKit's completion API in a withCheckedContinuation themselves.
Platform support and how small the package actually is
The badges at the top of the README describe the target. The package is built for Swift 6.0, and the platform badge lists iOS 15, tvOS 15 and visionOS 1, alongside the Swift and iOS logos, which is a wider set than a typical UIKit library and includes the new spatial platform. The macOS and watchOS names appear in the badge text as well. The package structure supports the drag-in story. The repository top level holds .gitignore, LICENSE, Package.swift, README.md, a Sources directory and the documentation directory, with no examples app, no test target directory and no CI configuration listed, so the deliverable is a library and a set of documents rather than a runnable reference project. The absence of an example application is the main practical difference from a pattern explained with a sample, and it is compensated by the four documentation files and the recommendation to read the Pattern document first, then the Library, then the Class, then the recommended Implementation. For a pattern whose value is in the shape of the code rather than in a single API, that progression is the point.
Where the pattern itself is the wrong answer
The honest limit is that a Coordinator solves coordination, and a pattern applied where it is not needed adds indirection. If your application has a handful of screens and one navigation stack, a view controller that pushes the next screen is simpler, and the pattern's own README frames it as a core architectural pattern worth a day or two of study, which is a signal that it is not a casual addition. There is also a cost in indirection that the author acknowledges: the screen you want to present is no longer something the view controller can simply present, so a developer reading the code has to follow the coordinator to find out what happens on a button tap. Second, the strict concurrency story means the 8.x line only fits a codebase that has already accepted Swift 6 semantics, or is willing to make that a prerequisite. Third, the library is UIKit-specific by design, which means it does not help a SwiftUI application, where the coordinator pattern has a different shape because view state rather than view controllers drives navigation. The MIT licence and the small footprint mean trying it is cheap, and the documentation is where the real cost of evaluation sits.
Editorial conclusion
Coordinator suits an iOS team whose screens have outgrown a view controller that both presents and owns navigation, since the pattern moves that responsibility into an object the caller holds, and the 8.x line is a reasonable target for a new Swift 6 codebase. It is the wrong tool if your app is small enough that a single view controller is still manageable, and it is the wrong tool if you are on an older Swift toolchain, because version 8 uses the Swift 6 language mode with strict concurrency turned on while 7.x and up was built with Swift 5.5 concurrency in mind. Verify first how you will consume the library, because the README offers two routes with different consequences, dragging the Coordinator folder into the project gives you the source to modify, while adding the repository URL through Swift Package Manager gives you a versioned dependency you cannot patch, and note that the last push was on 2026-06-05 with release 8.3 dated 2026-07-09.
Frequently asked questions
How do I install the Coordinator library?
You can drag the Coordinator folder into your project, since it is only a handful of files, or add the repository URL through Swift Package Manager, for which a Package.swift is provided at the root of the repository.
What changed in Coordinator 8.1.0?
Coordinator.init(rootViewController:) now takes a non-optional T instead of T?, CoordinatingQueuedMessage is now @MainActor () -> Void, and NavigationCoordinator gained async overloads of present(_:animated:) and dismiss(animated:) alongside the existing completion-based methods.
Which Swift version does version 8 of Coordinator require?
Version 8.x is using the Swift 6 language mode and has strict concurrency turned on. Version 7.x and up was made with Swift 5.5 concurrency in mind, and versions before that, the 6.x line, use closures.
Which Apple platforms does Coordinator support?
The platform badge in the README lists iOS 15, tvOS 15 and visionOS 1, alongside the Swift 6.0 and iOS markers.
Where should I start reading the Coordinator documentation?
The repository holds four documents: the Pattern document explains the design, the Library document covers usage, the Class document covers the API, and a recommended Implementation document gives the suggested approach. The README asks you to give the pattern a day or two and analyse it.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/radianttap-coordinator)Was this useful?