Class
Router
The base class for routers that do not own a view controller.
@MainActor class Router<InteractorType>
Mentioned In
Overview
Router is @MainActor-isolated. Its _children array is plain mutable state guarded by main-actor isolation alone — no locks are needed because every mutation of the array occurs through @MainActor API.
Overview
Subclass Router for headless napkins (a.k.a. “interactor-only” napkins) — units of business logic that have no view of their own but still attach child routers, listen to services, and expose a listener surface to their parent. For napkins that own a view, subclass ViewableRouter instead.
On deinit (which runs on the main actor) the router cancels any outstanding loaded() continuations and best-effort deactivates its own interactor along with each remaining child. deinit is isolated, which lets it touch main-actor state synchronously; the per-child deactivation is dispatched into a Task because Interactable calls are async.
Usage
@MainActor
final class HomeRouter: Router<HomeInteractor>, HomeRouting {
init(
interactor: HomeInteractor,
profileBuilder: ProfileBuildable
) {
self.profileBuilder = profileBuilder
super.init(interactor: interactor)
}
override func didLoad() async {
await super.didLoad()
// One-time setup, e.g. attaching a permanent child router.
}
func routeToProfile() async {
guard profileRouter == nil else { return }
let r = await profileBuilder.build(withListener: interactor)
profileRouter = r
await attachChild(r)
}
func routeBackFromProfile() async {
guard let r = profileRouter else { return }
profileRouter = nil
await detachChild(r)
}
private let profileBuilder: ProfileBuildable
private var profileRouter: ProfileRouting?
}
See Also
Routing
See Also
ViewableRouter
Topics
Creating a Router
Accessing the Interactor
Lifecycle
Managing Children
Relationships
Conforms To
Inherited By