iOS-Dokumentimporte auf einem entfernten Mac zuverlässig testen

iOS-Dokumentimporte auf einem entfernten Mac zuverlässig testen

Wenn Teams eine iOS-App über einen entfernten Mac debuggen, liegt ein Fehlschluss nahe: Ein PDF lässt sich in der Dateien-App auswählen und als Vorschau anzeigen – also scheint der Import abgeschlossen. Tatsächlich hat die App die externe Datei womöglich nur vorübergehend gelesen. Ist der ursprüngliche Pfad beim nächsten Start nicht mehr gültig, lässt sich der Eintrag in der Leseliste nicht öffnen. Zu prüfen ist daher nicht, ob die Dateiauswahl erscheint, sondern welche Zugriffsrechte, Besitzverhältnisse und Lebensdauer die Datei nach der Übergabe durch einen externen Anbieter hat.

Als Beispiel dient hier der Import eines PDFs, das dauerhaft zum Lesen verfügbar bleiben soll. Der Entwicklungs-Mac kann aus der Ferne bedient werden; maßgeblich für den Dateizugriff ist dennoch das iOS-Gerät, auf dem die App läuft. Implementierung und automatisierte Tests sind getrennt zu betrachten: Die Implementierung verarbeitet die tatsächlich von der Dateiauswahl gelieferte URL, die Tests prüfen die app-eigene Kopie und die Fehlerfälle.

Festlegen, wann der Import abgeschlossen ist

Eine Datei öffnen zu können, bedeutet nicht, sie zu besitzen. Bei UIDocumentPickerViewController(forOpeningContentTypes: [.pdf], asCopy: false) verweist die URL im Callback auf den von der Dateiauswahl bereitgestellten Speicherort. Sie sollte nicht als dauerhafter Pfad in einem Leseeintrag gespeichert werden. Soll die Datei auch beim nächsten Start verfügbar sein, muss die App das Original während der gültigen Zugriffszeit lesen, in ein eigenes dauerhaftes Verzeichnis kopieren und den Eintrag auf diese neue Kopie verweisen lassen.

Drei beobachtbare Ergebnisse sollten vorab feststehen: Beim Abbrechen der Auswahl entsteht kein neuer Eintrag; bei einem Kopierfehler entsteht kein als erfolgreich markierter Eintrag; nach einem erfolgreichen Import lässt sich die app-eigene Kopie auch nach einem Neustart öffnen, selbst wenn das Original verschoben wurde. Ein temporäres Verzeichnis eignet sich als Zwischenstation für einen Import, nicht als dauerhafte Bibliothek. Soll der Eintrag langfristig erhalten bleiben, wird die geprüfte temporäre Kopie anschließend in ein dauerhaftes App-Verzeichnis wie Application Support verschoben.

Der Import gilt erst nach dem Schreiben und Prüfen der Kopie als erfolgreich – nicht schon in dem Moment, in dem die Dateiauswahl eine URL zurückgibt.

Das koordinierte Kopieren während des gültigen Zugriffs abschließen

Sobald der Callback die URL liefert, aktiviert die App zunächst den Zugriff auf die sicherheitsbeschränkte Ressource und koordiniert das Lesen anschließend mit NSFileCoordinator. Die folgende Funktion zeigt nur das temporäre Ablegen eines einzelnen, kleinen PDFs. Wie der Inhalt geprüft, die Datei in ein dauerhaftes Verzeichnis verschoben und der Eintrag aktualisiert wird, muss der aufrufende Code festlegen. Das Beispiel verwendet den Öffnungsmodus asCopy: false und eignet sich nicht als allgemeine Kopierfunktion, die jede Quelle pauschal als extern autorisierte Datei behandelt.

func stagePickedPDF(_ url: URL) throws -> URL {
    guard url.startAccessingSecurityScopedResource() else {
        throw CocoaError(.fileReadNoPermission)
    }
    defer { url.stopAccessingSecurityScopedResource() }

    let destination = FileManager.default.temporaryDirectory
        .appendingPathComponent(UUID().uuidString)
        .appendingPathExtension("pdf")
    var coordinationError: NSError?
    var copyError: Error?

    NSFileCoordinator().coordinate(
        readingItemAt: url,
        options: [],
        error: &coordinationError
    ) { readableURL in
        do {
            try FileManager.default.copyItem(
                at: readableURL,
                to: destination
            )
        } catch {
            copyError = error
        }
    }

    if let coordinationError { throw coordinationError }
    if let copyError { throw copyError }
    return destination
}

coordinate ist ein synchroner Aufruf. Das Kopieren großer Dateien darf den UI-Thread nicht längere Zeit blockieren. In der Praxis kann der gesamte Ablauf – Zugriff aktivieren, Lesen koordinieren, Zugriff beenden – in einer Hintergrundaufgabe stattfinden. Der Zugriff darf nicht bereits im Callback beendet werden, bevor die externe URL an diese Aufgabe übergeben wird. Auch bei Fehlern muss die App den Zugriff beenden; defer lässt sich hier leichter überprüfen als verstreute manuelle Aufrufe.

Aus der temporären Datei einen wiederherstellbaren Eintrag machen

Nach dem Kopieren ist zunächst zu prüfen, ob die Kopie existiert, ihre Größe plausibel ist und ein PDF-Parser sie öffnen kann. Die Endung .pdf allein belegt keinen gültigen Inhalt. Erst nach erfolgreicher Prüfung wird die Datei in ein dauerhaftes App-Verzeichnis verschoben und ihr relativer Pfad unter einer von der App erzeugten Kennung gespeichert. Schlägt die Prüfung oder das Verschieben fehl, wird die temporäre Datei entfernt und ein Fehler mit Möglichkeit zum erneuten Versuch angezeigt. In die Leseliste darf dann kein Eintrag geschrieben werden.

Bei der dauerhaften Speicherung muss auch ein Abbruch zwischen dem Schreiben der Datei und dem Speichern des Eintrags berücksichtigt werden. Eine Möglichkeit ist, zunächst einen ausstehenden Eintrag anzulegen und ihn erst nach dem Verschieben als verfügbar zu markieren. Beim Start prüft die App unvollständige Einträge, gleicht sie mit den zugehörigen Dateien ab und entfernt Überreste. Die konkrete Transaktionslösung hängt von der Datenspeicherung der App ab. Das Ziel bleibt gleich: In der Liste dürfen keine Einträge auf nicht vorhandene Dateien verweisen.

Der von der Dateiauswahl gelieferte Anzeigename sollte nicht direkt an den Zielpfad angehängt werden. Ein von der App erzeugter Dateiname verhindert, dass gleichnamige Dateien einander überschreiben, und verringert Probleme durch Zeichen im Pfad. Der ursprüngliche Name lässt sich separat für die Anzeige speichern. Soll das Produkt statt einer Kopie stets das externe Original lesen, gilt ein anderes Zugriffsmodell: Erneute Autorisierung und eine Oberfläche für nicht verfügbare Quellen müssen eigens vorgesehen werden. Der Erfolgsstatus „lokal importiert“ passt dafür nicht.

Auf dem entfernten Mac in mehreren Ebenen testen

Zuerst erhält die Logik nach dem Import per XCTest PDF-Testdateien aus der App-Sandbox. Zu prüfen sind erfolgreiches Parsen, eine Fehlermeldung bei beschädigten Dateien, das Ausbleiben einer Überschreibung bei gleichen Dateinamen und die Frage, ob die Liste nach dem Löschen der temporären Datei weiterhin auf die dauerhafte Kopie verweist. Diese Testebene darf nicht als Nachweis für die Autorisierung sicherheitsbeschränkter Ressourcen gelten: Dateien aus der Sandbox unterliegen normalerweise nicht den Zugriffsbedingungen eines echten Dateianbieters.

Danach wird im Simulator die gesamte Oberfläche durchlaufen: Ein PDF, das in der Dateien-Auswahl sichtbar ist, wird vorbereitet; sowohl die Auswahl als auch das Abbrechen werden getestet. Nach dem Import wird die App beendet und neu gestartet, um zu prüfen, ob sich der Leseeintrag öffnen lässt. Anschließend wird die Quelldatei aus der Dateiauswahl verschoben: Liest die App tatsächlich ihre eigene Kopie? Verhalten von Dateianbietern, das sich nicht zuverlässig automatisieren lässt, gehört auf die Liste für manuelle Abnahmetests. Eine feste Wartezeit darf diese Unsicherheit nicht verdecken.

Abschließend werden Autorisierung und Downloadverhalten auf dem Zielgerät und mit den tatsächlich genutzten Dateianbietern überprüft. Manche Dokumente sind zum Zeitpunkt der Auswahl noch nicht vollständig lokal gespeichert. Schlägt das Lesen fehl, sollte die Oberfläche den Fehler anzeigen und eine erneute Auswahl ermöglichen, statt eine leere Kopie anzulegen. Geprüft wird hier die Fehlerbehandlung – nicht, wie lange ein Anbieter für den Download braucht.

Mit einer Matrix für Fehlerfälle abschließen

Aktion Erwartetes Ergebnis
Auswahl abbrechen Leseliste unverändert, keine temporäre Datei zurückgelassen
Quelle nicht lesbar Eindeutige Fehlermeldung, kein erfolgreicher Eintrag
Prüfung der Kopie fehlgeschlagen Temporäre Datei entfernt, erneuter Versuch möglich
Quelle nach dem Import verschieben App-eigene Kopie lässt sich nach einem Neustart weiterhin öffnen
App während des Imports unterbrechen Unvollständige Einträge werden beim nächsten Start erkannt und behandelt

Im Abnahmeprotokoll sollten Dateityp, Art der Quelle, System- und App-Build-Version sowie das tatsächliche Ergebnis jeder Aktion stehen. Wenn das Team ein Problem über den Remote-Desktop reproduziert, kann es so zuerst eingrenzen, ob der Fehler bei der Autorisierung, beim koordinierten Lesen, beim Kopieren, bei der Prüfung oder beim Speichern des Eintrags auftrat – statt immer wieder dieselbe Datei anzuklicken.

Häufig gestellte Fragen

Kann die vom Dokumentauswahldialog gelieferte URL dauerhaft gespeichert werden?

Verlassen Sie sich nicht auf den externen Pfad. Für dauerhaften Zugriff koordinieren Sie den Lesevorgang bei gültiger Berechtigung und kopieren die Datei in den persistenten App-Container.

Reicht ein Test im Simulator für den Dokumentimport aus?

Nein. Kopieren, Verarbeiten und Fehlerfälle lassen sich dort prüfen. Berechtigungen, Abbruch und verschobene Dateien sollten zusätzlich mit einem tatsächlichen Dateianbieter getestet werden.

XCZone · Cloud-Mac

Sie suchen einen exklusiven Mac, auf den Sie remote zugreifen können?

Vergleichen Sie Ausstattung, Standorte und Abrechnungszeiträume von M4 Start, M4 Work und M4 Pro – und finden Sie den passenden Tarif für Ihre Aufgaben.

Cloud-Mac-Tarife ansehen