Concepts
  • July 25, 2025

This framework uses three main concepts:

  • Route – an identifiable value that represents a destination in your app
  • Transition – a visual transition to be applied on a view
  • Coordinator – an object that maps routes to transitions and applies it on the current view hierarchy.

Getting Started


Basics


Definite a set of destinations

A destination could be a screen, a modal or even a dismiss action. Destinations are typically represented via enums.

enum AppDestination {
case first
case second
case third
}

Define a coordinator

There are three steps to defining a coordinator:

  1. You must subclass either UIViewControllerCoordinator or AppKitOrUIKitWindowCoordinator
  2. You must parametrize your subclass with a route.
  3. You must override and implement the function transition(for:), which is responsible for mapping a route to a transition.

class AppCoordinator: AppKitOrUIKitWindowCoordinator<AppDestination> {
override func transition(for route: AppDestination) -> ViewTransition {
switch route {
case .first:
return .present(Text(“First”))
case .second:
return .push(Text(“Second”))
case .third:
return .set(Text(“third”))
}
}
}

Integrate your coordinator

Coordinators can be integrated in a fashion similar to @EnvironmentObject. For this example, we’ll create an instance of the AppCoordinator defined in the previous section, and pass it to a ContentView via the View/coordinator(_:) function.

ContentView uses the coordinator via a special property wrapper, @Coordinator, which gives access to the nearest available coordinator for a given route type at runtime (in this case, AppCoordinator).

@main
struct App: SwiftUI.App {
@StateObject var coordinator = AppCoordinator()

var body: some Scene {
WindowGroup {
NavigationView {
ContentView()
.coordinator(coordinator)
}
}
}
}

struct ContentView: View {
@Coordinator(for: AppDestination.self) var coordinator

var body: some View {
VStack {
Button(“First”) {
coordinator.trigger(.first)
}

Button(“Second”) {
coordinator.trigger(.second)
}

Button(“Third”) {
coordinator.trigger(.third)
}
}
}
}

Ad-hoc Coordinators


If you wish to provide a scoped coordinator for a child view in SwiftUI, you can use View.coordinate to create an ad-hoc coordinator.

struct ContentView: View {
private enum MyRoute {
case foo
case bar
}

var body: some View {
NavigationView {
ChildView()
}
.coordinate(MyRoute.self) { route in
switch route {
case .foo:
return .push(Text(“Foo”))
case .bar:
return .present(Text(“Bar”))
}
}
}

private struct ChildView: View {
@Coordinator(for: MyRoute.self) var coordinator

var body: some View {
VStack {
Button(“Foo”) {
coordinator.trigger(.foo)
}

Button(“Bar”) {
coordinator.trigger(.bar)
}
}
}
}
}

In this example ContentView creates an ad-hoc coordinator via .coordinate(MyRoute.self) { .. } and provides it to a NavigationView containing ChildView.

ChildView can now access this coordinator using the @Coordinator property wrapper referencing the route type MyRoute declared inside ContentView.

In this example, only ContentView and types defined within its namespace can access MyRoute as it is marked as a private enum. It is good practice to scope your routes tightly wherever possible, as it allows you to reason about your navigation flows in a simpler way.

Custom Transitions


If you need lower level access to the underlying UIViewController  or UIWindow, use ViewTransition.custom to implement a custom transition.

In the following example, MyRoute.foo is implemented via a standard ViewTransition whereas MyRoute.bar is implemented as a custom one.

import Coordinator
import UIKit

enum MyRoute {
case foo
case bar
}

class MyViewCoordinator: UIViewControllerCoordinator<MyRoute> {
override func transition(for route: MyRoute) -> ViewTransition {
switch route {
case .foo:
return .present(Text(“Foo”))
case .bar:
return .custom {
guard let rootViewController = self.rootViewController else {
return assertionFailure()
}

// Use `rootViewController` to perform a custom transition.
rootViewController.present(
UIViewController(),
animated: true,
completion: { }
)
}
}
}
}

GitHub


View Github

YOU MIGHT ALSO LIKE...
MijickPopups Hero

  Popups Alerts Resizable Sheets Banners

SwiftUI Tooltip

This package provides you with an easy way to show tooltips over any SwiftUI view, since Apple does not provide ...

SimpleToast for SwiftUI

SimpleToast is a simple, lightweight, flexible and easy to use library to show toasts / popup notifications inside iOS or ...

SSToastMessage

Create Toast Views with Minimal Effort in SwiftUI Using SSToastMessage. SSToastMessage enables you to effortlessly add toast notifications, alerts, and ...

ToastUI

A simple way to show toast in SwiftUI   Getting Started • Documentation • Change Log