This is the second in an eight-part series on implementing data sharing in Shopping UK using CloudKit.
Shopping UK is a smart shopping list for UK shoppers. It knows almost every product in the supermarket and will arrange them by aisle. Lists can be shared with family or friends.
Last week, we introduced Shopping UK and discussed limitations of its old home-grown data sharing solution. Today, we’ll look at CloudKit’s basic concepts and how the Shopping UK schema is designed.
We’ll start with a quick review of the core CloudKit concepts.
If you’re already familiar with the concepts, please skip to the “Creating a CloudKit Schema” section below, which explains how CloudKit is used in Shopping UK.
CloudKit is one of Apple’s key technologies for sharing data in the cloud. Apple offers three options for data sharing:
CloudKit is a way to move structured data between your app and iCloud. It also has a web-based dashboard for viewing and manipulating the data in your own iCloud account (this is really useful for testing).
CloudKit is free to use. It is natively supported in iOS and it also has a JavaScript API so it can also be used from web sites and outside the Apple ecosystem.
Let’s look at three key concepts: Records, Record Types and Record Zones.
Data is stored in a CKRecord. Think of these like records in a relational database system.
Each CKRecord has a Record Type — a template for defining what values the CKRecord can contain. A Record Type has a name and a list of Keys. Each key is assigned a data-type (e.g String, Date, Bool).
Think of the Record Type like a table in a relational database system, and the Keys as fields.
To store books by an author, we might create two Record Types: Book and Author. A Book has a Title, a PublishedOn date, a number of Pages, an ISBN number and a link to an Author:
Together, the Record Type describe the “shape” of the data and how it links together — its schema. The data itself is represented by a CKRecord. This example uses a couple of my books from one of my favourite childhood authors, Roald Dahl:
A CKRecordZone is a grouping of CKRecords.
All CKRecords live in one and only one CKRecordZone.
A CKRecordZone lives in a CKDatabase. There are three databases: Public, Private and Shared (more on these later).
The Public and Private CKDatabases each have a Default CKRecordZone.
New, custom CKRecordZones can be created in the Private and Shared databases (but not in the Public database).
A CKDatabase lives in a CKContainer. There is typically only one CKContainer for the whole app.
This shows how these concepts relate to each other:
At first glance, the data structure for a shopping list would be similar to the Book/Author example above, with a parent “Shopping List” record and a set of child “ShoppingItem” records:
This is the way most tutorials approach the problem, and this is similar to the way Shopping UK stores data internally, but it isn’t the optimal structure for sharing a set of items on a list.
It is not enough to represent only the current state of the list. We need to see some history too, so we can answer questions like:
So instead of transferring a snapshot of the current list, Shopping UK transfers the ordered list of changes that have been applied to the list.
This “journal-based” approach is similar to how a relational database works internally (see write-ahead logging). It is a well-established pattern, but it isn’t appropriate for all apps. If you have an app that doesn’t need to track every change, a simple state-based sharing model, like the one shown earlier, would probably be simpler to implement.
When all changes have been applied to another device, the lists will become the same.
The journal-based approach has a couple of useful consequences:
Items don’t have an absolute position in the list. Instead, they know which item they follow. This means if my wife and I are both adding items to the list we won’t overwrite each other’s changes. Instead, each item will be added in turn.
Changes can be queued rather than being applied immediately. This is important when the app is in “Shopping” mode. It would be annoying if the app added an item to my checklist while I was shopping in the supermarket. It could cause me to mark-off the wrong item. Instead, the app will show the newly added items as notifications, and I can tap on them when I’m ready to include them in my checklist:
You’re probably wondering what happens after the list has been shared for several weeks and the journal contains thousands of changes. We’ll look at how the journal is compressed in a later post.
Next week, we’ll look at the lifecycle of a CKRecord: how they are created, read, modified and deleted.
If you get a chance, please try Shopping UK and let me know what you think at @wheelies