Umstieg auf die Dateien-App

Sorry, this entry is only available in German. For the sake of viewer convenience, the content is shown below in the alternative language. You may click the link to switch the active language.

Im heutigen Blog greife ich das Thema auf, wie ich unter iOS am besten lokale Dateien speichere und verarbeite. Noch spezifischer, wenn die Anforderung ist, dass der User die Datei mit einer externen App teilen kann, sie bearbeitet und wieder in die ursprüngliche App ladet.

Problembeschreibung

Bevor iOS 11 hatte ich zwei Möglichkeiten für Dateispeicherung – entweder mittels Realm oder einem App spezifischen „document directory“ – abhängig vom Use-Case. Um die Datei mit einer externen App teilen zu können, verwendete ich einen „UIActivityViewController“ und um die Dateien wieder zur originalen App zurück zu bekommen, wurde diese nach außen hin öffentlich gemacht und mittels der „share extension“ angezeigt. Das hat alles ganz gut geklappt, allerdings war es nicht ganz einfach die Ein- und Ausgänge im Blick zu behalten, da diese Anhänge Teil eines viel größeren Realm-Objekts waren.

Die „Dateien“-App als Lösung

Nachdem wir bei uns iOS 10 nicht mehr unterstützen, habe ich mich dazu entschlossen die Dateien-App zu benutzen, welche alle oben genannten Punkte ersetzt. Es war ein geeigneter Moment, da die App in Zukunft noch viel mehr benutzt werden wird. In dem Moment, in dem ich diese Zeilen schreibe, ist die Sektion „On my iPhone“ in der Dateien-App noch immer für Dateien, welche von Apps gespeichert werden, reserviert. Sobald iOS 13 erscheint, werden User die Möglichkeit haben, dort selbst Ordner für sich zu erstellen. Außerdem sollen USB-Sticks und SD-Karten unterstützt werden. Allerdings gibt es einen Punkt, der ganz wichtig für die App-Entwicklung ist: Das berühmte „document directory“ ist zugänglich über die Dateien-App. Dieser Ordner war niemals sichtbar für einen User, allerdings nutzten ihn Entwickler um Dateien intern zu speichern und abzurufen. Das ändert sich nun indem man einfach zwei Keys in „Info.plist“ ändert:

<key>UIFileSharingEnabled </key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>

Fertig. Jetzt hat die eigene App einen Ordner in der Dateien-App und die komplette Dateien-Struktur ist nun für den User und andere Apps zugänglich. Falls man Dateien doch vor dem User versteckt Speichern mag, gibt’s noch immer einige vordefinierte Ordner von Apple.

Dieser Code zeigt, wie die Ordner-Struktur erstellt wird. „BaseURL“ wird im „root“-Verzeichnis des Realm-Objekts gespeichert, welches auch andere angehängte Objekte enthält.


let basePath = ElectricCars/Tesla/Roadster/

let baseURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent(basePath)

if !FileManager.default.fileExists(atPath: baseURL.absoluteString) {

    do {

        try FileManager.default.createDirectory(atPath: baseURL.path, withIntermediateDirectories: true, attributes: nil)

    } catch {

        print(error)

    }

}

 

Wenn wir die Ordner-Struktur haben, gehen wir dazu über, die tatsächliche Datei in den Ordner zu speichern. „attachment data“ ist ein Teil des Realm-Objekts, welches die Daten als Entwurf speichert bis der User den „Speichern“-Button drückt. Wenn dieser gedrückt wird, wird eine Datei in den „documents folder“ der Dateien-App gespeichert, der Pfad zur Datei wird im Realm-Objekt gespeichert und die Daten selbst werden aus dem Realm-Objekt entfernt, da wir ab jetzt den Pfad zur Datei benutzen um an die Daten zu kommen.


do {

    try attachment.data!.write(to: baseURL.appendingPathComponent(attachment.name)) // name contains file extension

    try realm.write {

        attachment.path = attachment.name

        attachment.data = nil

    }

  } catch {

        print(error)

  }

 

Feinarbeit:

Um alles etwas flüssiger zu machen, verwenden wir „UIWebKit“ um das Dokument für eine Vorschau oder für das Teilen innerhalb der App bereit zu stellen. Ohne dem, alle Bearbeitungen in der Dateien-App würden auf die Dateien, welche in unserer App gespeichert sind, angewandt werden, welche eventuell an den Server geschickt werden.

*Bemerkung:
Falls man eine große App programmieren möchte, wo es hauptsächlich um Dokumente geht, sollte man sich eher die Integration der Dateien-App in die eigene ansehen, nicht andersherum (https://www.appcoda.com/files-app-integration/)