FO
ForgeObservers

Getting Started

Install ForgeObservers, create your first observer, and subscribe to system changes.

Requirements

  • iOS 18+
  • Swift 6.3+ (Xcode 26 or later)

Installation

Basic Usage

Every observer follows the same pattern: create it, read the current state synchronously, and subscribe to an AsyncStream for future changes.

Example.swift
import ForgeObservers

// 1. Create an observer
let connectivity = ConnectivityObserver()

// 2. Read current state
print(connectivity.status.isConnected) // true or false

// 3. Subscribe to changes
for await status in connectivity.statusStream {
    print("Connected: \(status.isConnected), via: \(status.interface)")
}

SwiftUI Integration

Use SwiftUI's .task modifier to subscribe to observer streams. The stream is automatically cancelled when the view disappears.

ContentView.swift
import SwiftUI
import ForgeObservers

struct ContentView: View {
    let connectivity: ConnectivityObserving

    @State private var isOffline = false

    var body: some View {
        VStack {
            if isOffline {
                Label("No Connection", systemImage: "wifi.slash")
                    .foregroundStyle(.red)
            }
            // ...
        }
        .task {
            for await status in connectivity.statusStream {
                isOffline = !status.isConnected
            }
        }
    }
}

ViewModel Integration

For more complex scenarios, inject observers into your ViewModel and use the .assign(to:on:) extension to bind streams to properties. Use async let to observe multiple streams concurrently.

AppViewModel.swift
import ForgeObservers

@Observable
final class AppViewModel {
    private let connectivity: ConnectivityObserving
    private let lifecycle: AppLifecycleObserving

    var isOffline = false
    var isInBackground = false

    init(
        connectivity: ConnectivityObserving,
        lifecycle: AppLifecycleObserving
    ) {
        self.connectivity = connectivity
        self.lifecycle = lifecycle
    }

    func startObserving() async {
        async let _: () = connectivity.statusStream
            .map { !$0.isConnected }
            .assign(to: \.isOffline, on: self)

        async let _: () = lifecycle.stateStream
            .map { $0 == .background }
            .assign(to: \.isInBackground, on: self)
    }
}

Observer Reference

ForgeObservers ships with 7 observers covering the most common system events:

Observer Protocol Model Stream
ConnectivityObserver ConnectivityObserving ConnectivityStatus statusStream
AppLifecycleObserver AppLifecycleObserving AppLifecycleState stateStream
KeyboardObserver KeyboardObserving KeyboardState stateStream
AppearanceObserver AppearanceObserving AppAppearance appearanceStream
LocaleObserver LocaleObserving AppLocale localeStream
ProtectedDataObserver ProtectedDataObserving ProtectedDataState stateStream
NotificationPermissionObserver NotificationPermissionObserving NotificationPermissionStatus statusStream

See the individual observer pages for detailed documentation on each observer.