Advertisement
  1. Code
  2. iOS

iOS von Grund auf mit Swift: Datenpersistenz und Sandboxing unter iOS

by
Read Time:14 minsLanguages:
This post is part of a series called iOS From Scratch With Swift.
iOS From Scratch With Swift: Exploring Tab Bar Controllers
iOS From Scratch With Swift: Building a Shopping List Application 1

German (Deutsch) translation by Katharina Grigorovich-Nevolina (you can also view the original English article)

Das Bestehen von Daten über Anwendungsstarts hinweg ist eine Anforderung, die die meisten iOS-Anwendungen erfüllen, vom Speichern von Benutzereinstellungen im Standardsystem bis zur Verwaltung großer Datenmengen in einer relationalen Datenbank. In diesem Artikel werden die gängigsten Strategien zum Speichern von Daten in einer iOS-Anwendung erläutert. Ich werde auch über das Dateisystem unter iOS sprechen und wie sich das Sandboxing von Anwendungen auf die Datenpersistenz auswirkt.

Einführung

Sie haben einen langen Weg zurückgelegt, Grashüpfer, und Sie haben viel gelernt. Es gibt jedoch einen wichtigen Aspekt der iOS-Entwicklung, den wir noch nicht besprochen haben: die Datenpersistenz. Nahezu jede iOS-Anwendung speichert Daten zur späteren Verwendung. Die Daten, die Ihre Anwendung speichert, können von Benutzereinstellungen über temporäre Caches bis hin zu großen relationalen Datensätzen reichen.

Bevor ich die gängigsten Datenpersistenzstrategien für Entwickler auf der iOS-Plattform diskutiere, werde ich einige Minuten damit verbringen, das Dateisystem und das Konzept des Anwendungs-Sandboxing zu diskutieren. Dachten Sie wirklich, Sie könnten die Daten Ihrer Anwendung im Dateisystem speichern, wo immer Sie möchten? Denken Sie nochmal nach, Padawan.

Sandboxing für Dateisysteme und Anwendungen

Die Sicherheit auf der iOS-Plattform hat seit der Einführung des iPhone im Jahr 2007 oberste Priorität. Im Gegensatz zu OS X-Anwendungen wird eine iOS-Anwendung in einer Anwendungssandbox abgelegt. Die Sandbox einer Anwendung verweist nicht nur auf das Sandbox-Verzeichnis einer Anwendung im Dateisystem. Es umfasst auch den kontrollierten und eingeschränkten Zugriff auf Benutzerdaten, die auf dem Gerät, den Systemdiensten und der Hardware gespeichert sind.

Mit der Einführung des Mac App Store hat Apple begonnen, das Sandboxing von Anwendungen auch unter OS X durchzusetzen. Obwohl die Einschränkungen für OS X-Anwendungen nicht so streng sind wie für iOS-Anwendungen, ist das Grundkonzept ähnlich. Es gibt jedoch Unterschiede. Die Anwendungssandbox einer iOS-Anwendung enthält beispielsweise das Anwendungspaket, was für OS X-Anwendungen nicht gilt. Die Gründe für diese Unterschiede sind hauptsächlich historisch.

Sandboxing und Verzeichnisse

Das Betriebssystem installiert jede iOS-Anwendung in einem Sandbox-Verzeichnis, das das Anwendungspaketverzeichnis und drei zusätzliche Verzeichnisse, Dokumente, Bibliothek und tmp enthält. Auf das Sandbox-Verzeichnis der Anwendung, das häufig als Home-Verzeichnis bezeichnet wird, kann durch Aufrufen der einfachen Foundation-Funktion NSHomeDirectory() zugegriffen werden.

Sie können dies selbst versuchen. Erstellen Sie ein neues Xcode-Projekt basierend auf der Single View-Anwendungsvorlage und nennen Sie es Datenpersistenz.

Project SetupProject SetupProject Setup

Öffnen Sie AppDelegate.swift und fügen Sie das obige Codefragment application_(:didFinishLaunchingWithOptions:) hinzu. Wenn Sie die Anwendung im Simulator ausführen, sollte die Ausgabe in der Konsole ungefähr so aussehen: 

Wenn Sie die Anwendung jedoch auf einem physischen Gerät ausführen, sieht die Ausgabe etwas anders aus, wie Sie unten sehen können. Die Anwendungssandbox und die auferlegten Einschränkungen sind jedoch identisch.

Das Abrufen des Pfads zum Dokument-Verzeichnis der Anwendung erfordert etwas mehr Arbeit, wie Sie im nächsten Codeausschnitt sehen können.

Wir rufen die Funktion NSSearchPathForDirectoriesInDomains() auf, die im Foundation-Framework definiert ist. Als erstes Argument übergeben wir DocumentDirectory vom Typ NSSearchPathDirectory, um anzuzeigen, dass wir nur am Documents-Verzeichnis der Anwendung interessiert sind. Das zweite und dritte Argument sind für unsere Diskussion von geringerer Bedeutung. Die Funktion gibt ein Array vom Typ [String] zurück, das ein Ergebnis enthält, den Pfad zum Dokument-Verzeichnis der Anwendung.

Warum Sandboxing?

Was ist der Vorteil von Sandboxing? Der Hauptgrund für Sandboxing-Anwendungen ist die Sicherheit. Durch die Beschränkung von Anwendungen auf ihre eigene Sandbox können gefährdete Anwendungen das Betriebssystem oder andere Anwendungen nicht beschädigen.

Mit kompromittierten Anwendungen meine ich sowohl gehackte Anwendungen, absichtlich böswillige Anwendungen als auch Anwendungen, die kritische Fehler enthalten, die versehentlich Schaden verursachen können.

Obwohl Anwendungen auf der iOS-Plattform in einer Sandbox gespeichert sind, können Anwendungen über eine Reihe von Systemschnittstellen den Zugriff auf bestimmte Dateien oder Assets anfordern, die sich außerhalb ihrer Anwendungssandbox befinden. Ein Beispiel hierfür ist die auf einem Gerät gespeicherte Musikbibliothek. Beachten Sie jedoch, dass die System-Frameworks für alle Vorgänge im Zusammenhang mit dem Dateizugriff verantwortlich sind.

Was geht wohin?

Obwohl Sie in der Sandbox Ihrer Anwendung so ziemlich alles tun können, was Sie wollen, hat Apple einige Richtlinien festgelegt, was wo gespeichert werden soll. Es ist aus mehreren Gründen wichtig, diese Richtlinien zu kennen. Wenn ein iOS-Gerät auf Ihrem Computer oder in iCloud gesichert wird, werden nicht alle Dateien in der Sandbox in die Sicherung einbezogen.

Das tmp-Verzeichnis sollte beispielsweise nur zum temporären Speichern von Dateien verwendet werden. Das Betriebssystem kann dieses Verzeichnis jederzeit leeren, z. B. wenn auf dem Gerät nur noch wenig Speicherplatz vorhanden ist. Das tmp-Verzeichnis ist nicht in Backups enthalten.

Das Dokumente-Verzeichnis ist für Benutzerdaten gedacht, während das Bibliothek-Verzeichnis für Anwendungsdaten verwendet wird, die nicht streng an den Benutzer gebunden sind. Das Caches-Verzeichnis im Bibliothek-Verzeichnis ist ein weiteres Verzeichnis, das nicht gesichert wird.

Beachten Sie auch, dass Ihre Anwendung den Inhalt des Anwendungspaketverzeichnisses nicht ändern soll. Das Anwendungspaketverzeichnis wird bei der Installation der Anwendung signiert. Durch Ändern des Inhalts des Anwendungspaketverzeichnisses in irgendeiner Weise wird die oben genannte Signatur geändert, was bedeutet, dass das Betriebssystem nicht zulässt, dass die Anwendung erneut gestartet wird. Dies ist eine weitere Sicherheitsmaßnahme von Apple zum Schutz der Kunden.

Datenpersistenzoptionen

Es gibt verschiedene Strategien zum Speichern von Anwendungsdaten auf der Festplatte. In diesem Artikel werfen wir einen kurzen Blick auf vier gängige Ansätze unter iOS:

  • Standardeinstellung System
  • Eigenschaftslisten
  • SQLite
  • Kerndatei

Die in diesem Artikel beschriebenen Optionen sollten nicht als austauschbar angesehen werden. Jede Strategie hat Vor- und Nachteile. Schauen wir uns zunächst das Standardsystem an.

Benutzerstandards

Das Standardsystem ist etwas, das iOS von OS X geerbt hat. Obwohl es zum Speichern von Benutzereinstellungen erstellt und entwickelt wurde, kann es zum Speichern aller Datentypen verwendet werden, sofern es sich um einen Eigenschaftslistentyp handelt: NSString, NSNumber, NSDate, NSArray, NSDictionary und NSData oder eine ihrer veränderlichen Varianten.

Was ist mit Swift-Datentypen? Zum Glück ist Swift klug genug. Es kann Zeichenfolgen und Zahlen speichern, indem es sie in NSString und NSNumber konvertiert. Gleiches gilt für Swift-Arrays und Wörterbücher.

Das Standardsystem ist nichts anderes als eine Sammlung von Eigenschaftslisten, eine Eigenschaftsliste pro Anwendung. Die Eigenschaftsliste wird in einem Voreinstellung-Ordner im Bibliothek-Ordner der Anwendung gespeichert und weist auf den Zweck und die Funktion der Eigenschaftsliste hin.

Einer der Gründe, warum Entwickler das Standardsystem mögen, ist, dass es so einfach zu bedienen ist. Schauen Sie sich das folgende Beispiel an, um zu sehen, was ich meine.

Durch Aufrufen von standardUserDefaults() in NSUserDefaults wird ein Verweis auf das gemeinsam genutzte Standardobjekt zurückgegeben.

In der letzten Zeile rufen wir synchronize() für das gemeinsam genutzte Standardobjekt auf, um Änderungen auf die Festplatte zu schreiben. Es ist selten erforderlich, synchronize() aufzurufen, da das Standardsystem bei Bedarf Änderungen speichert. Wenn Sie jedoch eine Einstellung mithilfe des Standardsystems speichern oder aktualisieren, kann es manchmal nützlich oder erforderlich sein, die Änderungen explizit auf der Festplatte zu speichern.

Auf den ersten Blick scheint das Standardsystem nichts anderes als ein Schlüsselwertspeicher zu sein, der sich an einem bestimmten Ort befindet. Die im Foundation-Framework definierte NSUserDefaults-Klasse ist jedoch mehr als eine Schnittstelle zum Verwalten eines Schlüsselwertspeichers. Weitere Informationen finden Sie in der Klassenreferenz.

Bevor wir fortfahren, fügen Sie das obige Code-Snippet in die Anwendungsmethode des Delegaten application_(:didFinishLaunchingWithOptions:) ein und führen Sie die Anwendung im Simulator aus. Öffnen Sie ein neues Finder-Fenster und navigieren Sie zu Bibliothek > Entwickler > CoreSimulator > Geräte> <DEVICE_ID> > Daten > Container > Daten > Anwendung> <APPLICATION_ID>.

<DEVICE_ID> und <APPLICATION_ID > sind zwei Bezeichner, die für den Simulator bzw. Ihre Anwendung eindeutig sind. Der Speicherort der Anwendungssandbox für den Simulator hängt von der verwendeten Xcode-Version ab. Wenn Sie Xcode 7 nicht verwenden, wird der Pfad wahrscheinlich anders sein.

Sie können Ihr Leben einfacher machen, indem Sie den Pfad zum Ausgangsverzeichnis Ihrer Anwendung zur Xcode-Konsole drucken. Fügen Sie die folgende Druckanweisung application(_:didFinishLaunchingWithOptions:) hinzu.

Der kryptisch benannte Ordner ist das Sandbox-Verzeichnis der Anwendung. Öffnen Sie im Sandbox-Verzeichnis der Anwendung den Einstellungen-Ordner im Bibliothek-Ordner und überprüfen Sie dessen Inhalt.

Application SandboxApplication SandboxApplication Sandbox

Sie sollten eine Eigenschaftsliste mit einem Namen sehen, der mit der Bundle-ID der Anwendung identisch ist. Dies ist der Standardspeicher für Ihre Anwendung. So sieht die Eigenschaftsliste in einem Texteditor aus. Wie Sie sehen können, wird die Eigenschaftsliste als XML-Datei auf der Festplatte gespeichert.

Wenn Sie den Zugriff auf die Sandbox einer Anwendung im Simulator erleichtern möchten, empfehlen wir Ihnen, sich SimPholders anzusehen. Es ist ein kleines Dienstprogramm, das die Arbeit mit dem Simulator sehr viel einfacher macht.

Eigenschaftslisten 

Wir haben bereits Eigenschaftslisten in dieser Reihe behandelt. Tatsächlich ist der Sicherungsspeicher der Benutzerstandarddatenbank eine Eigenschaftsliste. Die Verwendung von Eigenschaftslisten ist eine bequeme Strategie zum Speichern und Abrufen eines Objektdiagramms. Eigenschaftenlisten gibt es schon seit Ewigkeiten, sie sind einfach zu verwenden und daher eine hervorragende Option zum Speichern von Daten in einer iOS-Anwendung.

Wie bereits erwähnt, ist es wichtig zu beachten, dass in einer Eigenschaftsliste nur Eigenschaftslistendaten gespeichert werden können. Bedeutet dies, dass es nicht möglich ist, benutzerdefinierte Modellobjekte mithilfe von Eigenschaftslisten zu speichern? Das lässt sich machen. Benutzerdefinierte Modellobjekte müssen jedoch archiviert werden - eine Form der Serialisierung -, bevor sie in einer Eigenschaftsliste gespeichert werden können. Das Archivieren eines Objekts bedeutet einfach, dass das Objekt in einen Datentyp konvertiert werden muss, der in einer Eigenschaftsliste wie einer NSData-Instanz gespeichert werden kann.

Objekte archivieren

Erinnern Sie sich an das im Foundation Framework definierte NSCoding-Protokoll? Das NSCoding-Protokoll definiert zwei Methoden, init(coder:) und encodeWithCoder(_:). Eine Klasse implementiert diese Methoden, damit Instanzen der Klasse codiert und decodiert werden können.

Codierung und Decodierung sind die zugrunde liegenden Mechanismen für die Objektarchivierung und -verteilung. Wie die Objektarchivierung funktioniert, wird etwas später in dieser Serie klar. In dieser Lektion zeige ich Ihnen nur, wie Sie Arrays und Wörterbücher mithilfe von Eigenschaftslisten auf die Festplatte schreiben.

In Datei schreiben

Das folgende Code-Snippet soll Ihnen eine Vorstellung davon geben, wie einfach es ist, ein Array oder Wörterbuch auf die Festplatte zu schreiben. Theoretisch kann das in einer Eigenschaftsliste gespeicherte Objektdiagramm so komplex oder so groß sein, wie Sie möchten. Beachten Sie jedoch, dass Eigenschaftslisten nicht dazu gedacht sind, Dutzende oder Hunderte von Megabyte Daten zu speichern. Wenn Sie versuchen, sie auf diese Weise zu verwenden, führt dies wahrscheinlich zu einer Leistungsminderung.

Werfen wir einen Blick auf das obige Code-Snippet. Wir beginnen mit dem Speichern eines Verweises auf ein Array-Literal in einer Variablen namens fruits. Wir erstellen die Datei-URL zum Speichern der Eigenschaftsliste, die wir erstellen möchten. Die Datei-URL wird erstellt, indem eine Zeichenfolge an die Datei-URL des Dokumenten-Verzeichnisses angehängt wird. Die Zeichenfolge, die wir anhängen, ist der Name der Eigenschaftsliste, die wir in einer Sekunde erstellen, einschließlich der Erweiterung .plist.

Das Schreiben des Arrays auf die Festplatte ist so einfach wie das Aufrufen von writeToFile(_:atomically:) auf dem Array. Sie können das atomically Flag vorerst ignorieren. Wie das Beispiel zeigt, folgt das Schreiben eines Wörterbuchs auf die Festplatte einem ähnlichen Muster. Das Beispiel zeigt auch, wie Arrays und Wörterbücher aus einer Eigenschaftsliste erstellt werden. Dies haben wir jedoch bereits weiter oben in dieser Reihe behandelt. Führen Sie die Anwendung im Simulator aus und navigieren Sie zum Dokumenten-Verzeichnis der Anwendung. In diesem Verzeichnis sollten Sie die beiden soeben erstellten Eigenschaftslisten sehen.

Writing Objects to a Property ListWriting Objects to a Property ListWriting Objects to a Property List

So sieht die Eigenschaftsliste des Wörterbuchs aus, wenn Sie es in einem Texteditor öffnen.

SQLite

Wenn Ihre Anwendung datengesteuert ist und mit großen Datenmengen arbeitet, sollten Sie sich SQLite ansehen. Was ist SQLite? Der Slogan auf der SQLite-Website lautet "Klein. Schnell. Zuverlässig. Wählen Sie drei aus.", Was es gut zusammenfasst.

SQLite ist eine Bibliothek, die eine einfache eingebettete relationale Datenbank implementiert. Wie der Name schon sagt, basiert es genau wie MySQL und PostgreSQL auf dem SQL-Standard (Structured Query Language).

Der Hauptunterschied zu anderen SQL-Datenbanken besteht darin, dass SQLite portabel und sehr leicht ist. Anstelle eines separaten Prozesses, auf den über die Clientanwendung zugegriffen wird, ist SQLite serverlos. Mit anderen Worten, es ist in die Anwendung eingebettet oder wird von dem System verwaltet, auf dem die Anwendung ausgeführt wird, was bedeutet, dass es sehr schnell ist.

Die SQLite-Website behauptet, dass es sich um die am weitesten verbreitete SQL-Datenbank handelt. Ich weiß nicht, ob dies immer noch der Fall ist, aber es ist sicherlich eine beliebte Wahl für die clientseitige Datenspeicherung. Der Vorteil von SQLite gegenüber der direkten Arbeit mit Objekten besteht darin, dass SQLite viel, viel schneller ist. Dies liegt hauptsächlich daran, wie sich relationale Datenbanken und objektorientierte Programmiersprachen grundlegend unterscheiden.

Um die Lücke zwischen SQLite und Objective-C zu schließen, wurde im Laufe der Zeit eine Reihe von Object Relational Mapping(ORM)-Lösungen erstellt. Das ORM, das Apple für iOS und OS X erstellt hat, heißt Core Data. Wir werden uns das später in dieser Lektion ansehen.

FMDB von Flying Meat

Wenn Sie SQLite unter iOS verwenden, müssen Sie mit einer C-basierten Bibliothek arbeiten. Wenn Sie eine objektorientierte Lösung bevorzugen, empfehle ich den Objective-C-Wrapper von Gus Mueller (Flying Meat, Inc.) für SQLite, FMDB.

Die Bibliothek ist sehr performant. Ich habe in der Vergangenheit FMDB verwendet und war sehr zufrieden mit der API und der Robustheit und Zuverlässigkeit der Bibliothek.

Core Data 

Entwickler, die Core Data noch nicht kennen, verwechseln Core Data häufig mit einer Datenbank, während es sich tatsächlich um eine von Apple erstellte und verwaltete objektrelationale Mapping-Lösung handelt. Matt Gallagher hat einen großartigen Beitrag über die Unterschiede zwischen Core Data und einer Datenbank geschrieben. Core Data bietet ein relationales objektorientiertes Modell, das in einen XML-, Binär- oder SQLite-Speicher serialisiert werden kann. Core Data unterstützt sogar In-Memory-Speicher.

Warum sollten Sie Core Data anstelle von SQLite verwenden? Wenn Sie diese Frage stellen, nehmen Sie fälschlicherweise an, dass es sich bei Core Data um eine Datenbank handelt. Der Vorteil der Verwendung von Kerndaten besteht darin, dass Sie mit Objekten anstelle von Rohdaten arbeiten, z. B. Zeilen in einer SQLite-Datenbank oder Daten, die in einer XML-Datei gespeichert sind. Obwohl Core Data bei seiner ersten Veröffentlichung einige schwierige Jahre hinter sich hat, hat es sich zu einem robusten Framework mit vielen Funktionen entwickelt, darunter automatische Migrationen, Änderungsverfolgung, Fehler und integrierte Validierung.

Eine weitere großartige Funktion, die viele Entwickler zu schätzen wissen, ist der in Xcode integrierte Core Data-Modelleditor. Mit dem Editor können Entwickler das Datenmodell der Anwendung über eine grafische Oberfläche modellieren.

Core Data Model EditorCore Data Model EditorCore Data Model Editor

Ob Core Data die richtige Lösung für Ihre Anwendung ist, hängt von den Daten ab, die Sie verwalten möchten, sowohl in Bezug auf die Datenmenge als auch auf das zugrunde liegende Modell. Wenn Sie sehr große Datenmengen verwalten möchten, kann Core Data im Laufe der Zeit zu einem Leistungsengpass werden. In diesem Fall ist SQLite möglicherweise die bessere Lösung.

iCloud

Sie haben wahrscheinlich schon von iCloud gehört und fragen sich möglicherweise, wo iCloud in die Geschichte der Datenpersistenz passt. Im Gegensatz zu SQLite und Core Data ist iCloud keine Form der Datenpersistenz. Stattdessen handelt es sich um eine Plattform oder einen Dienst zum Bereitstellen von Benutzerdaten auf mehreren Geräten und mehreren Instanzen einer Anwendung - oder sogar einer Familie von Anwendungen.

Die iCloud-Plattform umfasst mehrere Dienste oder Komponenten. Die Komponente, die uns interessiert, ist iCloud Storage, das vier Arten von Speicher umfasst:

  • CloudKit
  • Schlüsselwertspeicher
  • Dokumentenspeicher
  • Core Data-Speicher

Wenn Sie mehr über iCloud Storage erfahren möchten, empfehle ich, meine Serie über iCloud Storage zu lesen.

Schlussfolgerung

Sie sollten jetzt eine gute Vorstellung von den Optionen haben, die Sie zum Speichern von Daten bei der Entwicklung für die iOS-Plattform benötigen. Denken Sie daran, dass nicht alle von uns behandelten Strategien gleich sind.

Diese Serie geht langsam zu Ende. In den nächsten beiden Abschnitten erstellen wir eine weitere Anwendung, um das bisher Gelernte in die Praxis umzusetzen. Der beste Weg zu lernen ist zu tun.

Wenn Sie Fragen oder Kommentare haben, können Sie diese in den Kommentaren unten hinterlassen oder mich auf Twitter erreichen.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.