Getting Started
Install ForgeObservers, create your first observer, and subscribe to system changes.
Requirements
- iOS 18+
- Swift 6.3+ (Xcode 26 or later)
Installation
- Open your project in Xcode.
- Go to File → Add Package Dependencies…
- Paste the repository URL:
https://github.com/stefanprojchev/ForgeObservers.git - Set the version rule to Up to Next Major from
1.0.0. - Select your app target and click Add Package.
dependencies: [
.package(url: "https://github.com/stefanprojchev/ForgeObservers.git", from: "1.0.0")
] targets: [
.target(
name: "YourApp",
dependencies: ["ForgeObservers"]
)
] swift package add-dependency https://github.com/stefanprojchev/ForgeObservers.git --from 1.0.0 Basic Usage
Every observer follows the same pattern: create it, read the current state synchronously, and subscribe to an AsyncStream for future changes.
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.
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.
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.