How Vorssaint Manages Feature State Using Combine

Vorssaint uses Combine's ObservableObject pattern with a singleton FeatureRuntime class that publishes state changes via @Published, enabling reactive synchronization across SwiftUI views and background services.

Vorssaint's feature-state architecture centers on reactive programming through Apple's Combine framework. The implementation in vorssaint/vorssaint-utils eliminates manual state polling by broadcasting changes through a centralized runtime, ensuring UI components and services respond instantly to configuration updates.

The Core Architecture: FeatureRuntime

The FeatureRuntime class in [Sources/Vorssaint/App/FeatureRuntime.swift](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/App/FeatureRuntime.swift) serves as the single source of truth for all feature availability.

Key implementation details:

  • Singleton pattern: Accessed via FeatureRuntime.shared
  • ObservableObject conformance: Required for Combine integration
  • @Published private(set) var revision: The reactive trigger that increments on every state mutation

When any feature's availability changes, the finishAvailabilityChange() method increments revision. This single property drives the entire reactive pipeline.

// Conceptual runtime structure as implemented in FeatureRuntime.swift
final class FeatureRuntime: ObservableObject {
    static let shared = FeatureRuntime()
    
    @Published private(set) var revision: UInt = 0
    
    private init() {}
    
    func setAvailable(_ feature: AppFeature, _ available: Bool) {
        // Update UserDefaults, execute binding closures, then:
        finishAvailabilityChange()
    }
    
    private func finishAvailabilityChange() {
        revision += 1
    }
}

Observing State in SwiftUI Views

SwiftUI views consume the runtime through @ObservedObject, creating automatic subscriptions to revision changes.

The [Sources/Vorssaint/UI/Settings/MonitorSettings.swift](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/UI/Settings/MonitorSettings.swift) implementation demonstrates this pattern for the "Combine usage and temperature" toggle and similar controls:

struct FeatureHubView: View {
    @ObservedObject private var runtime = FeatureRuntime.shared

    var body: some View {
        List {
            ForEach(AppFeature.allCases) { feature in
                Toggle(feature.title,
                       isOn: Binding(
                         get: { feature.isAvailable },
                         set: { runtime.setAvailable(feature, $0) }))
            }
        }
    }
}

The @ObservedObject wrapper establishes a Combine subscriber. When revision increments, SwiftUI invalidates the view and triggers a rebuild—no explicit .onChange handler required for basic refresh behavior.

Binding Features to UserDefaults

Feature state persists through @AppStorage keys defined in [Sources/Vorssaint/Core/Defaults.swift](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/Core/Defaults.swift). The runtime maintains a static bindings dictionary mapping features to reactive closures.

The flow works as follows:

  1. User toggles a feature in UI
  2. setAvailable() writes to the corresponding UserDefaults key
  3. The binding closure executes, calling syncWithPreferences() on the relevant service
  4. finishAvailabilityChange() increments revision
  5. All subscribers receive the update
// Triggering a state change programmatically
FeatureRuntime.shared.setAvailable(.monitorCPU, true)

This single call cascades through: preference storage → service synchronization → UI refresh.

Service-Level Combine Integration

Background services in Vorssaint import Combine directly and subscribe to runtime changes. Services like WindowMaximizer and AutoQuitService implement syncWithPreferences() methods that react to the revision stream.

A typical service implementation:

final class WindowMaximizer {
    static let shared = WindowMaximizer()
    private var cancellable: AnyCancellable?

    private init() {
        cancellable = FeatureRuntime.shared.$revision
            .sink { [weak self] _ in
                self?.syncWithPreferences()
            }
    }

    func syncWithPreferences() {
        // Read current FeatureRuntime state and UserDefaults
        // Start or stop maximizer logic based on availability
    }
}

The $revision syntax accesses the Published wrapper's Publisher interface, creating a type-erased AnyCancellable subscription that survives for the service's lifetime.

Command-Bar Synchronization

The [Sources/Vorssaint/App/CommandBarService.swift](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/App/CommandBarService.swift) demonstrates cross-cutting reactive behavior. After each revision increment, CommandBarService.shared.noteHubChange() re-evaluates available feature rows using internal Combine publishers.

This ensures the command palette—often detached from the main view hierarchy—remains synchronized with ground-truth state without direct view-to-view communication.

Why Combine Over Alternatives

Vorssaint's Combine-based approach provides specific advantages for feature state:

Aspect Implementation
Propagation speed Synchronous publisher delivery
Memory safety Automatic cancellation via AnyCancellable
Threading Receive on RunLoop.main for UI updates
Composability Operators chain for complex derived state

The @Published property wrapper abstracts away PassthroughSubject or CurrentValueSubject boilerplate while maintaining full Combine compatibility for services requiring manual subscription control.

Summary

  • FeatureRuntime acts as the centralized ObservableObject with a @Published revision counter
  • SwiftUI views use @ObservedObject for automatic refresh on state changes
  • Services subscribe directly to $revision via sink to trigger background work
  • UserDefaults provides persistence, with reactive bindings triggering service updates
  • Single revision increment propagates changes instantly across all system layers

Frequently Asked Questions

What triggers a UI refresh in Vorssaint's feature system?

The @Published var revision in FeatureRuntime triggers refreshes. Any SwiftUI view observing the runtime via @ObservedObject automatically rebuilds when revision increments, which occurs after every setAvailable() call through finishAvailabilityChange().

How do background services know when to start or stop?

Services subscribe to FeatureRuntime.shared.$revision using Combine's sink operator. When the revision changes, the subscription executes syncWithPreferences(), allowing the service to read current availability and adjust its operation accordingly.

Why use a revision counter instead of @Published properties for each feature?

A single revision counter reduces publisher overhead and simplifies subscription management. Services and views rarely need granular per-feature updates; they typically re-scan all relevant preferences when any feature changes. This trade-off minimizes Combine subscription complexity across the codebase.

Where is feature availability actually stored?

Availability persists in UserDefaults via @AppStorage keys defined in Sources/Vorssaint/Core/Defaults.swift. The runtime reads and writes these keys while maintaining the reactive ObservableObject layer for in-memory synchronization.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →