FO
ForgeObservers

ConnectivityObserver

Monitors network reachability and connection details using Apple's NWPathMonitor.

Model

ConnectivityStatus is a struct that provides detailed information about the current network state, including connection type and data constraints.

ConnectivityStatus & ConnectionInterface
public struct ConnectivityStatus: Sendable, Equatable {
    /// Whether the device has network connectivity.
    public let isConnected: Bool
    /// The type of network interface currently in use.
    public let interface: ConnectionInterface
    /// True when using cellular data or a personal hotspot.
    public let isExpensive: Bool
    /// True when Low Data Mode is enabled.
    public let isConstrained: Bool

    /// A convenience default for the disconnected state.
    public static let disconnected = ConnectivityStatus(
        isConnected: false,
        interface: .none,
        isExpensive: false,
        isConstrained: false
    )
}

public enum ConnectionInterface: Sendable, Equatable {
    case wifi
    case cellular
    case wiredEthernet
    case other
    case none
}

Default value -- Use ConnectivityStatus.disconnected as a safe default when initializing state before the first stream emission.

Protocol

ConnectivityObserving
public protocol ConnectivityObserving: Sendable {
    /// The current connectivity status.
    var status: ConnectivityStatus { get }

    /// An AsyncStream that emits connectivity changes.
    var statusStream: AsyncStream<ConnectivityStatus> { get }
}

Usage

Reading current state
let connectivity = ConnectivityObserver()

// Check if online
if connectivity.status.isConnected {
    print("Online via \(connectivity.status.interface)")
}

// Check connection type
if connectivity.status.interface == .wifi {
    startLargeDownload()
}

// Check if the connection is metered
if connectivity.status.isExpensive {
    useLowBandwidthMode()
}

// Check Low Data Mode
if connectivity.status.isConstrained {
    skipPrefetching()
}

Stream

Reacting to changes
// React to connectivity changes
for await status in connectivity.statusStream {
    if status.isConnected {
        await resumeSync()
    } else {
        pauseSync()
    }
}

// Conditionally start large operations
for await status in connectivity.statusStream {
    if status.interface == .wifi && !status.isConstrained {
        await prefetchAssets()
    }
}