import Foundation import Network import OSLog /// Wrapper um `NWPathMonitor`. Feuert das übergebene Closure bei jedem /// Wechsel von "kein Pfad" → "Pfad da" (= Wifi/Mobil wieder verfügbar /// nach Offline). Ein wechselnder Pfad (Wifi → Mobil) feuert nicht /// erneut — wir wollen nur die Reconnect-Flanke. /// /// Lebenszyklus liegt beim App-Root. Stop-Methode existiert, aber /// reale App startet Watcher einmal beim Launch und lässt ihn bis /// zum Prozess-Ende laufen. final class ReachabilityWatcher: @unchecked Sendable { private let monitor = NWPathMonitor() private let queue = DispatchQueue(label: "ev.mana.zitare.reachability") private let log = Logger(subsystem: "ev.mana.zitare", category: "reachability") private var wasReachable: Bool? private var onReconnect: @Sendable () -> Void = {} func start(onReconnect: @escaping @Sendable () -> Void) { self.onReconnect = onReconnect monitor.pathUpdateHandler = { [weak self] path in guard let self else { return } let reachable = path.status == .satisfied let prev = self.wasReachable self.wasReachable = reachable if prev == false, reachable { self.log.info("Reachable again — triggering reconnect-hook") self.onReconnect() } else if prev == nil { self.log.info("Initial reachability: \(reachable ? "yes" : "no", privacy: .public)") } } monitor.start(queue: queue) } func stop() { monitor.cancel() } }