Erstellen einer Einkaufslistenanwendung mit CloudKit: Einführung
() translation by (you can also view the original English article)
Bereits 2012 führte Apple iCloud neben iOS 5 ein. Gleichzeitig kündigte das Unternehmen an, dass Entwickler über eine Reihe von APIs auf iCloud zugreifen können. Zunächst hatten Entwickler drei Optionen:
Diese APIs sind jedoch nicht perfekt. Ein großes Manko ist die mangelnde Transparenz. Insbesondere die Integration von Kerndaten hat selbst bei den erfahrensten Entwicklern zu Frustration und Verwirrung geführt. Wenn etwas schief geht, haben Entwickler keine Ahnung, was oder wer der Schuldige ist. Es könnte ein Problem in ihrem Code oder in Apples sein.
CloudKit
Auf der WWDC 2014 stellte Apple CloudKit vor, ein brandneues Framework, das direkt mit den iCloud-Servern von Apple interagiert. Das Framework ist vergleichbar mit einer Reihe von PaaS-Lösungen (Platform as a Service) wie Firebase. Wie Firebase bietet Apple eine flexible API und ein Dashboard, mit denen Entwickler einen Einblick in die auf den iCloud-Servern von Apple gespeicherten Daten erhalten.
Was mir an CloudKit am besten gefällt, ist Apples eigenes Engagement für das Framework. Laut Angaben des Unternehmens basieren iCloud Drive und iCloud Photo Library auf CloudKit. Dies zeigt, dass das CloudKit-Framework und seine Infrastruktur robust und zuverlässig sind.
Als Entwickler ist dieses Zeichen von Vertrauen und Engagement wichtig. In der Vergangenheit veröffentlichte Apple gelegentlich APIs, die von Fehlern geplagt wurden oder denen wichtige Funktionen fehlten, nur weil das Unternehmen kein eigenes Hundefutter aß. Dies gilt nicht für CloudKit. Und das ist vielversprechend.
Sollten Sie CloudKit verwenden?
Schlüsselwertspeicherung und Dokumentenspeicherung haben ihre Verwendung, und Apple betont, dass CloudKit vorhandene iCloud-APIs nicht ersetzt oder ablehnt. Gleiches gilt für Core Data. CloudKit bietet beispielsweise keinen lokalen Speicher. Dies bedeutet, dass eine Anwendung, die auf einem Gerät ohne Netzwerkverbindung ausgeführt wird, praktisch unbrauchbar ist, wenn sie ausschließlich auf CloudKit basiert.
Apple betont außerdem, dass die Fehlerbehandlung bei der Arbeit mit CloudKit von entscheidender Bedeutung ist. Wenn beispielsweise ein Speichervorgang fehlschlägt und der Benutzer nicht benachrichtigt wird, weiß er möglicherweise nicht einmal, dass seine Daten nicht gespeichert wurden - und verloren gegangen sind.
CloudKit ist eine großartige Lösung zum Speichern von strukturierten und nicht strukturierten Daten in der Cloud. Wenn Sie eine Lösung für den Zugriff auf Daten auf mehreren Geräten benötigen, sollten Sie CloudKit in Betracht ziehen.
Auf der WWDC 2015 hat Apple das getan, was nur wenige Entwickler erwartet oder erhofft hatten. Es wurde ein Webdienst für CloudKit angekündigt. Dies bedeutet, dass CloudKit auf praktisch jeder Plattform verwendet werden kann, einschließlich Android und Windows Phone.
Die Preise von Apple sind auch ziemlich wettbewerbsfähig. Der Einstieg in CloudKit ist kostenlos und für die meisten Anwendungen kostenlos. Auch hier ist CloudKit sicherlich eine Überlegung wert, wenn Sie Daten in der Cloud speichern möchten.
CloudKit-Konzepte
Entwickler, die mit Kerndaten zu kämpfen haben, sind mit den Bausteinen des Frameworks häufig nicht vertraut. Wenn Sie sich nicht die Zeit nehmen, den Core Data Stack kennenzulernen und zu verstehen, werden Sie unweigerlich auf Probleme stoßen. Gleiches gilt für CloudKit.
Bevor wir mit der Arbeit an einer Beispielanwendung beginnen, die CloudKit verwendet, möchte ich Ihnen einige Minuten lang einige wichtige Konzepte des CloudKit-Frameworks und der CloudKit-Infrastruktur vorstellen. Beginnen wir mit Containern, Datenbanken und Sandboxing.
Datenschutz und Eindämmung
Apple macht sehr deutlich, dass Datenschutz ein wichtiger Aspekt von CloudKit ist. Das erste, was Sie wissen müssen, ist, dass jede Anwendung einen eigenen Container in iCloud hat. Dieses Konzept ist sehr ähnlich zu der Art und Weise, wie iOS-Anwendungen jeweils eine eigene Sandbox haben. Es ist jedoch möglich, einen Container für andere Anwendungen freizugeben, solange diese Anwendungen demselben Entwicklerkonto zugeordnet sind. Wie Sie sich vorstellen können, eröffnet dies Entwicklern eine Reihe interessanter Möglichkeiten.
Ein CloudKit-Container enthält mehrere Datenbanken. Jeder Container verfügt über eine öffentliche Datenbank, in der Daten gespeichert werden können, auf die jeder Benutzer Ihrer Anwendung zugreifen kann. Neben der öffentlichen Datenbank enthält ein Container auch eine private Datenbank für jeden Benutzer Ihrer Anwendung. Die private Datenbank des Benutzers wird zum Speichern von Daten verwendet, die für diesen bestimmten Benutzer spezifisch sind. Die Trennung und Kapselung von Daten ist eine Schlüsselkomponente der CloudKit- und iCloud-Infrastruktur.
Obwohl der Container einer Anwendung viele Datenbanken enthalten kann, enthält ein Container aus Entwicklersicht nur zwei Datenbanken: die öffentliche Datenbank und die private Datenbank des Benutzers, der derzeit bei seinem iCloud-Konto angemeldet ist. Ab 2017 führte Apple eine dritte Datenbank ein, die gemeinsam genutzte Datenbank, mit der Apps eine Teilmenge von Datensätzen freigeben können, die in der privaten Datenbank eines anderen Benutzers freigegeben sind, und sie auffordern, zu diesen offengelegten Datensätzen beizutragen.
Ich werde etwas später mehr über iCloud-Konten sprechen.
Aufzeichnungen und Aufzeichnungszonen
Die Datenbanken der Container-Speicherdatensätze einer Anwendung. Dies unterscheidet sich nicht sehr von einer herkömmlichen Datenbank. Auf den ersten Blick scheinen die in einer CloudKit-Datenbank gespeicherten Datensätze nichts anderes als Wrapper für ein Wörterbuch von Schlüssel-Wert-Paaren zu sein. Sie mögen wie verherrlichte Wörterbücher aussehen, aber das ist nur ein Teil der Geschichte.
Jeder Datensatz hat auch einen Datensatztyp und eine Reihe von Metadaten-Feldern. Die Metadaten eines Datensatzes verfolgen, wann der Datensatz erstellt wurde, welcher Benutzer den Datensatz erstellt hat, wann der Datensatz zuletzt aktualisiert wurde und wer den Datensatz aktualisiert hat.
Die CKRecord
-Klasse repräsentiert einen solchen Datensatz und ist eine ziemlich mächtige Klasse. Die Werte, die Sie in einem Datensatz speichern können, sind nicht auf Eigenschaftslistentypen beschränkt. Sie können Zeichenfolgen, Zahlen, Datumsangaben und Datenblobs in einem Datensatz speichern. Die CKRecord
-Klasse behandelt jedoch auch die Standortdaten CLLocation
als erstklassigen Datentyp.
Sie können sogar Arrays der unterstützten Datentypen in einem Datensatz speichern. Mit anderen Worten, Arrays von Zeichenfolgen oder Zahlen sind für eine CKRecord
-Instanz kein Problem.
Datensätze sind in Datensatzzonen organisiert. Eine Datensatzzone gruppiert verwandte Datensätze. Die öffentliche und die private Datenbank verfügen jeweils über eine Standardaufzeichnungszone. Bei Bedarf können jedoch benutzerdefinierte Aufzeichnungszonen erstellt werden. Aufzeichnungszonen sind ein fortgeschrittenes Thema, auf das wir in dieser Reihe nicht näher eingehen werden.
Beziehungen
Beziehungen zwischen Datensätzen werden von Instanzen der CKReference
-Klasse verwaltet. Schauen wir uns ein Beispiel an, um besser zu verstehen, wie genau Beziehungen funktionieren. Die Anwendung, die wir in dieser Reihe erstellen, verwaltet eine Reihe von Einkaufslisten. Jede Liste kann null oder mehr Elemente enthalten. Dies bedeutet, dass jedes Element einen Verweis auf die Liste haben muss, zu der es gehört.



Es ist wichtig zu verstehen, dass das Element einen Verweis auf die Liste enthält. Während es möglich ist, ein Array von CKReference
-Instanzen für die Elemente einer Liste zu erstellen, ist es bequemer - und empfohlen -, den Fremdschlüssel beim Element und nicht bei der Liste beizubehalten. Dies empfiehlt auch Apple.
Die Art und Weise, wie CloudKit Beziehungen verwaltet, ist recht einfach, bietet jedoch die Möglichkeit, die untergeordneten Elemente eines Datensatzes automatisch zu löschen, wenn der übergeordnete Datensatz gelöscht wird. Wir werden uns die Beziehungen etwas später in dieser Serie genauer ansehen.
Vermögenswerte
Ich möchte auch die CKAsset
-Klasse erwähnen. Während es möglich ist, Datenblobs in einem Datensatz zu speichern, sollten unstrukturierte Daten (wie Bilder, Audio und Video) als CKAsset
-Instanzen gespeichert werden. Eine CKAsset
-Instanz ist immer einem Datensatz zugeordnet und entspricht einer Datei auf der Festplatte. Wir werden in dieser Serie nicht mit der CKAsset
-Klasse arbeiten.
Authentifizierung
Sie sind sich sicher einig, dass CloudKit sehr ansprechend aussieht. Es gibt jedoch ein wichtiges Detail, das wir noch nicht besprochen haben: die Authentifizierung. Benutzer authentifizieren sich über ihre iCloud-Konten. Benutzer, die nicht in einem iCloud-Konto angemeldet sind, können keine Daten in iCloud schreiben.
Dies gilt zwar für alle iCloud-APIs. Beachten Sie jedoch, dass Anwendungen, die ausschließlich auf CloudKit basieren, in diesem Fall nicht sehr funktionsfähig sind. Der Benutzer kann lediglich auf die Daten in der öffentlichen Datenbank zugreifen, sofern der Entwickler dies zulässt.
Daten lesen
Benutzer, die nicht bei ihren iCloud-Konten angemeldet sind, können weiterhin Daten aus der öffentlichen Datenbank lesen. Es versteht sich von selbst, dass auf die private Datenbank nicht zugegriffen werden kann, da iCloud nicht weiß, wer die Anwendung verwendet.
Lesen und Schreiben
Nach der Anmeldung können Benutzer in die öffentliche und ihre private Datenbank lesen und schreiben. Ich habe bereits erwähnt, dass Apple den Datenschutz sehr ernst nimmt. Infolgedessen sind die in der privaten Datenbank gespeicherten Datensätze nur für den Benutzer zugänglich. Selbst Sie als Entwickler können die Daten, die Benutzer in ihren privaten Datenbanken gespeichert haben, nicht sehen. Dies ist der Nachteil von Apple bei der Verwaltung des Backends Ihrer Anwendung, aber für den Benutzer ein klarer Gewinn.
Einkaufsliste
Die Anwendung, die wir erstellen werden, verwaltet Ihre Einkaufslisten. Jede Einkaufsliste hat einen Namen und null oder mehr Artikel. Nach dem Erstellen der Einkaufslistenanwendung sollten Sie sich mit dem CloudKit-Framework in einem eigenen Projekt ziemlich wohl fühlen.
Voraussetzungen
In diesem Tutorial verwende ich Xcode 9 und Swift 4. Wenn Sie eine ältere Version von Xcode verwenden, denken Sie daran, dass Sie eine andere Version der Programmiersprache Swift verwenden. Dies bedeutet, dass Sie den Quellcode des Projekts aktualisieren müssen, um den Compiler zufrieden zu stellen. Die Änderungen sind größtenteils geringfügig, aber es ist wichtig, sich dessen bewusst zu sein.
Da CloudKit ein fortgeschrittenes Thema ist, gehe ich davon aus, dass Sie sowohl mit Xcode als auch mit der Programmiersprache Swift vertraut sind. Wenn Sie mit der iOS-Entwicklung noch nicht vertraut sind, empfehle ich, zuerst ein Einführungs-Tutorial zu lesen oder an einem unserer Kurse zur Swift-Entwicklung teilzunehmen:
- SwiftErstellen Sie iOS-Apps mit SwiftMarkus Mühlberger
- DesignmusterSchnelle DesignmusterDerek Jensen
Überprüfen Sie diese, wenn Sie mit der iOS-Entwicklung oder der Swift-Sprache noch nicht vertraut sind.
Projektaufbau
Es ist Zeit, Code zu schreiben. Starten Sie Xcode und erstellen Sie ein neues Projekt basierend auf der Single View-Anwendung-Vorlage.



Geben Sie Ihrem Projekt einen Namen und eine Organisationskennung. Die resultierende Bundle-ID wird verwendet, um die ID des Standardcontainers Ihrer Anwendung zu erstellen. Diese Kennung muss für alle Entwicklerkonten eindeutig sein, da sie einen globalen Namespace gemeinsam nutzen. Es ist daher wichtig, den Ratschlägen von Apple zu folgen und die umgekehrte Domainnamen-Notation zu verwenden.



ICloud aktivieren
Der nächste Schritt ist die Aktivierung von iCloud und CloudKit. Wählen Sie das Projekt im Projektnavigator links aus und wählen Sie das Ziel für Ihre Anwendung aus der Liste der Ziele aus. Öffnen Sie die Registerkarte Allgemein und stellen Sie Team auf das richtige Team ein. Stellen Sie im nächsten Schritt sicher, dass Ihr Entwicklerkonto über die erforderlichen Berechtigungen zum Erstellen einer App-ID verfügt, um Probleme zu vermeiden.



Öffnen Sie als Nächstes oben die Registerkarte Funktionen und setzen Sie den Schalter für iCloud auf Ein. Xcode benötigt einen Moment, um eine App-ID in Ihrem Namen zu erstellen. Außerdem werden der App-ID die erforderlichen Berechtigungen hinzugefügt. Wenn dies nicht funktioniert, stellen Sie sicher, dass das Team richtig eingestellt ist und Sie über die erforderlichen Berechtigungen zum Erstellen einer App-ID verfügen.



Das Aktivieren von CloudKit ist so einfach wie das Aktivieren des Kontrollkästchens CloudKit. Standardmäßig verwendet Ihre Anwendung den Standardcontainer für Ihre Anwendung. Dieser Container wird automatisch für Sie erstellt, wenn Sie CloudKit aktivieren.
Wenn Ihre Anwendung Zugriff auf einen anderen Container oder auf mehrere Container benötigt, aktivieren Sie das Kontrollkästchen Benutzerdefinierte Container angeben und die Container, auf die Ihre Anwendung Zugriff benötigt.



Möglicherweise haben Sie bemerkt, dass Xcode Ihr Ziel automatisch mit dem CloudKit-Framework verknüpft hat. Dies bedeutet, dass Sie bereit sind, CloudKit in Ihrer Anwendung zu verwenden.
Machen Sie Ihre Füße nass
Im nächsten Tutorial dieser Reihe werden wir die Möglichkeit hinzufügen, Einkaufslisten hinzuzufügen, zu bearbeiten und zu entfernen. Zum Abschluss dieses Tutorials möchte ich Ihnen jedoch die Füße nass machen, indem ich Ihnen zeige, wie Sie mit der CloudKit-API interagieren. Alles, was wir tun werden, ist den Datensatz des aktuell angemeldeten Benutzers abzurufen.
Öffnen Sie ViewController.swift und fügen Sie oben eine Importanweisung hinzu, um das CloudKit-Framework zu importieren.
1 |
import UIKit |
2 |
import CloudKit |
Um den Benutzerdatensatz abzurufen, müssen wir zuerst die Kennung des Datensatzes abrufen. Mal sehen, wie das funktioniert. Ich habe eine Hilfsmethode, fetchUserRecordID
, erstellt, die die Logik zum Abrufen der Datensatzkennung des Benutzers enthält. Wir rufen diese Methode in der viewDidLoad
-Methode des View Controllers auf.
1 |
override func viewDidLoad() { |
2 |
super.viewDidLoad() |
3 |
|
4 |
// Fetch User Record ID
|
5 |
fetchUserRecordID() |
6 |
}
|
Die Implementierung von fetchUserRecordID
ist etwas interessanter als viewDidLoad
. Wir rufen zuerst einen Verweis auf den Standardcontainer der Anwendung ab, indem wir defaultContainer
für die CKContainer
-Klasse aufrufen. Wir rufen dann fetchUserRecordIDWithCompletionHandler(_:)
auf defaultContainer
auf. Diese Methode akzeptiert einen Abschluss als einziges Argument.
1 |
private func fetchUserRecordID() { |
2 |
// Fetch Default Container
|
3 |
let defaultContainer = CKContainer.default() |
4 |
|
5 |
// Fetch User Record
|
6 |
defaultContainer.fetchUserRecordID { (recordID, error) -> Void in |
7 |
if let responseError = error { |
8 |
print(responseError) |
9 |
|
10 |
} else if let userRecordID = recordID { |
11 |
DispatchQueue.main.sync { |
12 |
self.fetchUserRecord(recordID: userRecordID) |
13 |
}
|
14 |
}
|
15 |
}
|
16 |
}
|
Der Abschluss akzeptiert zwei Argumente: eine optionale CKRecordID
-Instanz und eine optionale NSError
-Instanz. Wenn error
nil
ist, packen wir die recordID
sicher aus.
Es ist wichtig zu betonen, dass der Abschluss in einem Hintergrund-Thread aufgerufen wird. Dies bedeutet, dass Sie vorsichtig sein müssen, wenn Sie die Benutzeroberfläche Ihrer Anwendung innerhalb eines von CloudKit aufgerufenen Abschlusses aktualisieren. In fetchUserRecordID
rufe ich beispielsweise explizit fetchUserRecord(_:)
im Hauptthread auf.
In fetchUserRecord(_:)
rufen wir den Benutzerdatensatz ab, indem wir CloudKit mitteilen, an welchem Datensatz wir interessiert sind. Beachten Sie, dass wir fetchRecordWithID(_:CompletionHandler:)
für das privateDatabase
-Objekt aufrufen, eine Eigenschaft des defaultContainer
-Objekts.
Die Methode akzeptiert eine CKRecordID
-Instanz und einen Completion-Handler. Letzterer akzeptiert eine optionale CKRecord
-Instanz und eine NSError
-Instanz. Wenn wir den Benutzerdatensatz erfolgreich abgerufen haben, drucken wir ihn in die Xcode-Konsole.
1 |
private func fetchUserRecord(recordID: CKRecordID) { |
2 |
// Fetch Default Container
|
3 |
let defaultContainer = CKContainer.default() |
4 |
|
5 |
// Fetch Private Database
|
6 |
let privateDatabase = defaultContainer.privateCloudDatabase |
7 |
|
8 |
// Fetch User Record
|
9 |
privateDatabase.fetch(withRecordID: recordID) { (record, error) -> Void in |
10 |
if let responseError = error { |
11 |
print(responseError) |
12 |
|
13 |
} else if let userRecord = record { |
14 |
print(userRecord) |
15 |
}
|
16 |
}
|
17 |
}
|
Wenn Sie die App in Xcode ausführen, wird in der Konsole Folgendes angezeigt:



Dies hätte Ihnen einen Eindruck vom CloudKit-Framework vermitteln sollen. Die moderne API ist intuitiv und einfach zu bedienen. Im nächsten Tutorial werden wir uns eingehender mit den Möglichkeiten der CloudKit-API befassen.
Sie können das gesamte Beispielprojekt bei GitHub klonen (Tag #introduction
).
Abschluss
Sie sollten nun die Grundlagen des CloudKit-Frameworks richtig verstehen. Der Rest dieser Serie konzentriert sich auf die Erstellung der Einkaufslistenanwendung. Im nächsten Tutorial fügen wir zunächst die Möglichkeit hinzu, Einkaufslisten hinzuzufügen, zu bearbeiten und zu entfernen.