SwiftUIEx (2026)

After enough SwiftUI screens, I noticed I was writing the same scaffolding over and over: a UIHostingController subclass, a model that owns the dependencies and constructs the view-model, a weak reference back to the view controller for navigation, the same wiring on every single screen. The per-screen content was small; the boilerplate around it was not.

SwiftUIEx is a tiny library that absorbs that boilerplate into three types:

@Observable @MainActor
final class BookNoteListScreenModel: HostingScreenModel {
    weak var viewController: UIViewController?
    lazy var viewModel = BookNoteListViewModel(
        selectNote: { [weak self] note in
            self?.handleSelect(note)
        }
    )
}

final class BookNoteListScreen:
    HostingScreen<BookNoteListScreenModel, BookNoteListView> {}

That’s the entire screen-level plumbing. What’s left for each new screen is the actual model, view-model, and view content… the per-screen stuff.

It commits hard to @Observable. No Combine, no @State per property, no @Bindable gymnastics — just a shared observable view-model that the view reads from and the model writes to. Navigation stays in app code, not in the framework, so you can structure it however you want.

Source on github.