SwiftUI Integration
A RootView driven by an @Observable orchestrator. Startup actions control which screen renders via shared state.
App State
An @Observable singleton holds the flags and CompletionSignal references that actions write to inside execute(). Views read from it to decide what to display.
import SwiftUI
import ForgeOrchestrator
@Observable
final class TaskFlowState {
static let shared = TaskFlowState()
var showOnboarding = false
var onboardingSignal: CompletionSignal?
var showForceUpdate = false
var forceUpdateSignal: CompletionSignal?
} RootView
The root view observes TaskFlowState and renders the appropriate screen. The .task modifier registers and evaluates actions — they run once when the view appears. register() is synchronous; only evaluate() needs await.
import SwiftUI
import ForgeOrchestrator
struct RootView: View {
@Environment(SequenceOrchestrator.self) var orchestrator
@State private var state = TaskFlowState.shared
var body: some View {
Group {
if state.showForceUpdate {
ForceUpdateView(signal: state.forceUpdateSignal)
} else if state.showOnboarding {
OnboardingView(signal: state.onboardingSignal)
} else {
MainTabView()
}
}
.task {
// register() is @MainActor and synchronous — only evaluate() needs await
orchestrator.register(ForceUpdateAction())
orchestrator.register(OnboardingAction())
await orchestrator.evaluate()
}
}
} OnboardingView
Receives the CompletionSignal as a parameter — the action created it inside execute() and stored it on shared state. On "Get Started", the view updates state and calls signal.complete(), which resumes the orchestrator and allows the next action to run.
struct OnboardingView: View {
let signal: CompletionSignal?
var body: some View {
NavigationStack {
VStack(spacing: 24) {
Text("Welcome to TaskFlow")
.font(.largeTitle.bold())
Text("Organize your tasks, hit your goals.")
.multilineTextAlignment(.center)
.foregroundStyle(.secondary)
Spacer()
Button("Get Started") {
UserDefaults.standard.set(true, forKey: "onboardingComplete")
TaskFlowState.shared.showOnboarding = false
signal?.complete()
}
.buttonStyle(.borderedProminent)
}
.padding(32)
}
}
} App Entry Point
Create the orchestrator once in App and inject it into the environment. RootView handles all registration and evaluation via its own .task.
import SwiftUI
import ForgeOrchestrator
@main
struct TaskFlowApp: App {
@State private var orchestrator = SequenceOrchestrator()
var body: some Scene {
WindowGroup {
RootView()
.environment(orchestrator)
}
}
}