iOS-Netzwerkstatus prüfen: NWPathMonitor richtig einordnen
Ein Nutzer tippt auf „Aktualisieren“, die App meldet „Netzwerk nicht verfügbar“ – und beim nächsten Versuch klappt es doch. Häufig liegt das nicht an der Anfrageverarbeitung, sondern daran, dass die App einen noch nicht aktualisierten Netzwerkpfadstatus als Voraussetzung für das Senden einer Anfrage verwendet. Wer iOS-Apps auf einem Cloud-Mac entwickelt, kann das Zustandsmodell zunächst mit deterministischen Ereignisfolgen prüfen. Simulator und echtes Gerät dienen anschließend dazu, das Systemverhalten zu kontrollieren. Dafür muss die Remoteverbindung nicht immer wieder unterbrochen werden, um Fehler zu provozieren.
Statushinweise und Anfrageergebnisse trennen
NWPathMonitor beobachtet Netzwerkpfade, die seinen Überwachungskriterien entsprechen. .satisfied garantiert weder, dass der Server erreichbar ist, noch, dass die Authentifizierung gültig ist. .requiresConnection bedeutet, dass zunächst eine Verbindung aufgebaut werden muss, und darf nicht pauschal als dauerhafter Offlinezustand interpretiert werden.
Auf Anwendungsebene sollten mindestens vier Zustände unterschieden werden: „unbekannt“, „Pfad verfügbar“, „Verbindung erforderlich“ und „Pfad nicht verfügbar“. Solange nach dem Start noch kein Callback eingetroffen ist, bleibt der Zustand unbekannt; die App sollte nicht standardmäßig von „offline“ ausgehen. Zeitüberschreitungen bei API-Anfragen, Authentifizierungsfehler und Serverfehler gehören jeweils in das Modell für Anfrageergebnisse und dürfen nicht rückwirkend den Pfadstatus überschreiben.
Der Netzwerkstatus eignet sich für Hinweise, nicht als zentraler Schalter, der sämtliche Anfragen verbietet. Ob ein vom Nutzer angestoßener erneuter Versuch funktioniert, sollte die tatsächliche Anfrage zeigen.
Dieser Ansatz ist für Apps sinnvoll, die Netzwerkbanner oder Hinweise zu automatischen Wiederholungsversuchen benötigen. Soll eine Funktion lediglich eine einzelne Anfrage senden, ist es oft einfacher, direkt deren Ergebnis zu verarbeiten, statt zusätzlich eine Überwachung einzubauen.
Ein unabhängig ausführbares Zustandsmodell aufbauen
Erstellen Sie in der Kommandozeile des entfernten macOS-Systems die Datei NetworkStateCheck.swift mit dem folgenden vollständigen Inhalt. Das Modell benötigt kein echtes Netzwerk. Eine Generationsnummer unterscheidet die einzelnen Monitorinstanzen. Das Beispiel setzt serielle Aufrufe voraus; parallele Änderungen aus mehreren Queues sind damit nicht ohne Weiteres zulässig.
enum PathState: Equatable {
case unknown, available, needsConnection, unavailable
}
struct NetworkHint {
private(set) var generation = 0
private(set) var state: PathState = .unknown
private(set) var expensive = false
private(set) var constrained = false
mutating func restart() -> Int {
generation += 1
state = .unknown
expensive = false
constrained = false
return generation
}
mutating func accept(
generation incoming: Int,
state next: PathState,
expensive: Bool = false,
constrained: Bool = false
) {
guard incoming == generation else { return }
state = next
self.expensive = expensive
self.constrained = constrained
}
}
var hint = NetworkHint()
precondition(hint.state == .unknown)
let old = hint.restart()
hint.accept(generation: old, state: .available, expensive: true)
precondition(hint.state == .available && hint.expensive)
let current = hint.restart()
hint.accept(generation: old, state: .unavailable)
precondition(hint.state == .unknown)
hint.accept(generation: current, state: .needsConnection)
precondition(hint.state == .needsConnection)
hint.accept(generation: current, state: .available, constrained: true)
precondition(hint.constrained && !hint.expensive)
hint.accept(generation: current, state: .unavailable)
precondition(hint.state == .unavailable)
hint.accept(generation: current, state: .available)
precondition(hint.state == .available && !hint.constrained)
Führen Sie xcrun swift NetworkStateCheck.swift aus. Bei Erfolg erscheint keine Ausgabe; schlägt eine Prüfung fehl, endet der Prozess mit einem Exitstatus ungleich null. Geprüft wird das von der App festgelegte Zustandsverhalten, nicht die Korrektheit des Netzwerkstacks des Betriebssystems.
Beim Einbinden des Monitors eine feste Reihenfolge einhalten
Der Adapter für den Produktivbetrieb importiert Network und erstellt NWPathMonitor(). Setzen Sie zuerst pathUpdateHandler und rufen Sie erst danach start(queue:) auf. Bilden Sie die drei Werte von NWPath.Status auf die Zustands-Enum des Modells ab und übergeben Sie zusätzlich isExpensive und isConstrained. Unbekannte, künftig hinzukommende Enum-Werte werden dem Zustand „unbekannt“ zugeordnet.
Erfassen Sie beim Erstellen des Monitors die aktuelle Generationsnummer. Bevor ein Callback das Zustandsmodell erreicht, muss diese erneut verglichen werden. Soll die Überwachung neu gestartet werden, erhöhen Sie zuerst die Generationsnummer, damit alte Ereignisse ungültig werden. Beenden Sie anschließend die alte Instanz und erstellen Sie zuletzt eine neue. Eine bereits beendete Instanz darf nicht erneut gestartet werden.
Der Lebenszyklus des Monitors und die Modellaktualisierungen gehören in denselben seriellen Ausführungskontext. Wenn Sie dafür den Hauptausführungskontext verwenden, prüfen Sie die Generationsnummer erst nach dem Wechsel dorthin. Andernfalls können bereits eingereihte alte Ereignisse den neuen Zustand weiterhin verfälschen. Auch bei der Veröffentlichung an die Oberfläche muss diese Reihenfolge erhalten bleiben, damit mehrere asynchrone Zustellungen den Zustand nicht in umgekehrter Reihenfolge überschreiben.
Verwenden Sie requiredInterfaceType: .wifi nicht als alleinige Grundlage für die Entscheidung, ob das Gerät eine Netzwerkverbindung hat. Damit werden nur Pfade für einen bestimmten Schnittstellentyp beobachtet; andere verfügbare Pfade können unberücksichtigt bleiben. Nutzen Sie diesen Initialisierer nur, wenn die Funktion tatsächlich auf diese Schnittstelle beschränkt ist.
Grenzfälle mit einer Ereignismatrix abdecken
Überführen Sie das Skript in das Unit-Test-Target Ihres Projekts. Jeder Testfall erhält ein eigenes Modell. Ergänzen Sie mindestens folgende Prüfungen:
- Nach dem Start trifft kein Callback ein: Der Zustand bleibt unbekannt, Anfragen dürfen weiterhin gesendet werden.
- Der Pfad ist verfügbar, aber eine API-Anfrage schlägt fehl: Nur der Anfragefehler wird aktualisiert; die Oberfläche meldet keinen Verbindungsabbruch des Pfads.
- Ein zuvor nicht verfügbarer Pfad wird wieder verfügbar: Das Banner verschwindet, ohne denselben fachlichen Vorgang erneut auszulösen.
- Nach dem Beenden trifft ein altes Ereignis ein: Weder Zustand noch Kostenhinweis ändern sich.
- Dasselbe Ereignis trifft mehrfach ein: Der Hinweis bleibt konsistent, und es sammeln sich keine zusätzlichen Wiederholungsaufgaben an.
- Der Status für kostenintensive oder eingeschränkte Verbindungen ändert sich: Angepasst wird nur die Downloadstrategie im Rahmen der fachlichen Vorgaben.
isExpensive steht nicht für einen bestimmten Schnittstellentyp, und isConstrained bedeutet nicht, dass das Gerät vollständig offline ist. Bei großen Dateiübertragungen lassen sich ergänzend die Richtlinien von URLSessionConfiguration für kostenintensive und eingeschränkte Netzwerke einsetzen. Nutzeraktionen dürfen nicht allein aufgrund des Hinweismodells stillschweigend verworfen werden.
Automatisierte Prüfungen und Geräteabnahme abgrenzen
Der Simulator eignet sich, um Banner, Schaltflächen und die Anbindung des Zustandsmodells zu prüfen. Sein Netzwerkverhalten hängt jedoch vom Host ab. Ein geänderter Hinweis im Simulator ist kein Nachweis dafür, dass der Wechsel auf Mobilfunk erfolgreich geprüft wurde. Deaktivieren Sie für Tests insbesondere nicht die Netzwerkschnittstelle des Cloud-Macs: Dadurch kann die Remotedesktopverbindung abbrechen.
Prüfen Sie auf einem echten Gerät zusätzlich den Wechsel zwischen drahtlosen Netzwerken, eingeschränkte Netzwerkverbindungen und die Rückkehr aus dem Hintergrund. Halten Sie jeweils die Reihenfolge der Pfadereignisse, die Änderungen der Oberfläche und die Anfrageergebnisse fest. Eine vom Testserver abgelehnte Verbindung und ein nicht verfügbarer Netzwerkpfad sind unterschiedliche Szenarien; dokumentieren Sie die Nachweise getrennt.
Reichen Sie abschließend das Zustandsmodell, die Ereignistests und die Protokolle der Geräteprüfungen ein. Das Abnahmekriterium ist nicht, dass das Banner den Netzwerkzustand immer sofort richtig errät. Entscheidend ist, dass Hinweise keine Anfragen fälschlich blockieren, alte Monitorinstanzen keine neue Sitzung überschreiben und nach einem Fehler klar geregelt ist, wie Nutzeraktionen weiterverarbeitet werden.
Häufig gestellte Fragen
Bedeutet satisfied, dass die API erreichbar ist?
Nein. Der Status beschreibt einen passenden Netzwerkpfad, prüft aber weder Server noch Anmeldung oder Antwortinhalt. Entscheidend bleibt die tatsächliche Anfrage.
Wie werden verspätete Callbacks nach cancel abgefangen?
Vor dem Abbruch die Generation im selben seriellen Ausführungskontext erhöhen. Jeder Callback trägt seine ursprüngliche Generation; nur aktuelle Ereignisse werden übernommen. Für einen Neustart einen neuen Monitor erstellen.
Prüfen Sie Ihren eigenen Workflow auf einem Remote-Mac.
Mieten Sie einen exklusiv für Sie bereitgestellten Mac mini M4 und nutzen Sie macOS mit grafischer Oberfläche und Terminal. Ideal, um Verbindung und Workflow zu testen. Für länger laufende Offline-Aufgaben oder den Anschluss professioneller Hardware sollten Sie auch einen Kauf in Betracht ziehen.
Exklusiven Mac mini mieten