Default `--self remove` strippt `self.` aus @autoclosure-Calls (Logger.info) und Closure-Captures, was Swift-6-strict-concurrency dann als "implicit use of self in closure" rejected. Default `redundantSendable` strippt `Sendable` von Codable-DTOs, die über actor-Grenzen wandern müssen. Beide Regeln aus. Zusätzlich Lauf über alle Files: harmlose Whitespace-/ Trailing-Comma-/Optional-Init-Normalisierung in 5 Files. `self.` und `Sendable` bleiben überall erhalten. Build grün. Hintergrund: η-0-Lauf hat das aktiv gemacht und Submit-DTOs zerschossen, die ich dann von Hand revertieren musste. Dieser Commit verhindert die Wiederholung in η-1+. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
40 lines
1.5 KiB
Swift
40 lines
1.5 KiB
Swift
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()
|
|
}
|
|
}
|