Chapters

Hide chapters

Core Data by Tutorials

Eighth Edition · iOS 14 · Swift 5.3 · Xcode 12

Core Data by Tutorials

Section 1: 11 chapters
Show chapters Hide chapters

10. NSPersistentCloudKit Container
Written by Aaron Douglas

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

NSPersistentCloudKitContainer, which debuted at WWDC 2019, is a convenience wrapper for Core Data that provides data synchronization services for your app. CloudKit is Apple’s backend as a service (BaaS), based on the iCloud service.

Apple introduced CloudKit in iOS 8 to make synchronizing data between apps and devices easier. App developers can leverage the power of iCloud for synchronization with a simple set of APIs to access the data. CloudKit has APIs for iOS, macOS and JavaScript for the web.

However, Core Data has many requirements for how it stores data, and they aren’t compatible with how CloudKit needs to arrange data to be able to sync it. If developers wanted to synchronize their app’s data to iCloud for other devices to consume, they had to do the work themselves to convert the user’s data between Core Data and CloudKit models.

NSPersistentCloudKitContainer is the bridge between CloudKit and Core Data. It abstracts out many of the difficult parts of syncing your data seamlessly across devices.

Understanding CloudKit’s strengths

Core Data, as you’ve seen, is a powerful data persistence framework. It’s easy to start using it and to integrate it with your app.

Core Data isn’t just useful for the data that your users type into apps. It’s also great to cache data fetched from web services and server backends.

However, not every app has a complex backend powering it. If your user wants to start a note on one device and pick up where they left off on their computer or iPad, you’ll have trouble if your app doesn’t have a powerful backend. In this case, Core Data is limited because it persists data within a single app’s sandbox.

CloudKit solves that problem. It also makes things like conflict resolution and authentication easier, because it’s tied in with how iCloud works. Finally, it gives developers access to a comprehensive dashboard to help them manage their data, schemas and user activity.

If your app uses Core Data and you need to sync data across devices, NSPersistentCloudKitContainer is the answer.

Preparing to use NSPersistentCloudKitContainer

CloudKit requires a paid Apple Developer account to function. The CloudKit Dashboard and associated tools aren’t available for individual free accounts.

Getting started with Core Data and CloudKit

To see how easy it is to use CloudKit with Core Data, you’ll create a quick demo app. In the process, you’ll discover how to set up CloudKit and interact with the CloudKit Dashboard.

Setting up your project

Start by creating a new project in Xcode. Select the iOS platform and App in the template chooser.

var body: some View {
  NavigationView {
    List {
      ForEach(items) { item in
        Text(
          "Item at \(item.timestamp!, formatter: itemFormatter)"
        )
      }
      .onDelete(perform: deleteItems)
    }
    .toolbar {
      Button(action: addItem) {
        Label("Add Item", systemImage: "plus")
      }
    }
    .navigationTitle("Items")
  }
}

container.viewContext.automaticallyMergesChangesFromParent
  = true

Adding custom types

Next, you’ll tell CloudKit about your data model.

Viewing your data

The Dashboard also gives you the ability to see the data, not just the schema. Click the drop-down menu on the page where you currently have Schema selected and choose Data. You’ll see the query tool that lets you find data in CloudKit.

Fixing the error

You get this error because when you first upload your schema, none of the Core Data fields are queryable, nor is the CloudKit field recordName. You’ll change that next.

Editing and syncing your records

Now, try editing the record through the CloudKit Dashboard — you’re going to test just how magical CloudKit is.

Introducing the Dog Doodies app

When someone gets a new dog, they want to make sure they understand their pet’s needs. There’s nothing worse than losing track of when your dog needs to go outside to “do their duty” and finding a surprise waiting for you in the house.

Configuring CloudKit

Configuring CloudKit for this project is similar to the configuration you did for the simple demo app.

Convert the container to CloudKit

The first and only step to convert Dog Doodies over to CloudKit is to replace the persistent container class with NSPersistentCloudKitContainer.

private lazy var storeContainer: NSPersistentContainer = {
  // 1
  let container = 
    NSPersistentCloudKitContainer(name: self.modelName)
  container.loadPersistentStores { _, error in
    if let error = error as NSError? {
      print("Unresolved error \(error), \(error.userInfo)")
    }
  }

  // 2
  container.viewContext.automaticallyMergesChangesFromParent
    = true

  // 3
  do {
    try container.viewContext.setQueryGenerationFrom(.current)
  } catch {
    fatalError("###\(#function): Failed to pin viewContext to the current generation:\(error)")
  }

  return container
}()

Log some doodies!

Build and run the app. After it launches, you’ll see a “No Dog Selected” message.

Looking at CloudKit data

What does all this data look like in CloudKit?

Understanding CloudKit’s weaknesses

Like most things in life, if something seems too easy, you probably did it wrong. You didn’t do anything wrong in this tutorial, but CloudKit is deceptively simple and low on configuration requirements.

Model versioning

Over time, your data model will change. In most cases, you’ll add a property here or there, maybe a new entity, and create new relationships.

Automatically merging

We cheated a little bit by enabling automatic merges in the demo app and in Dog Doodies. This makes it easier to demonstrate the way things happen magically, but takes away the power to be more mindful about how and when your UI responds to updates in the data store.

Debugging CloudKit

Inevitably, something will go wrong with a data sync and you’ll need to dig into the sync mechanism. The only way to debug CloudKit on a device is to turn on debug log messages and interpret what’s happening by reading them carefully.

Testing on iCloud

You’ll need to test your app before releasing it to production, and this isn’t very easy on iCloud, especially if you aren’t the only developer on the project.

Key points

  • NSPersistentCloudKitContainer is a powerful addition to Core Data to power multi-device sync for your app.
  • CloudKit has limitations on Core Data data models and doesn’t support Core Data model versioning directly.
  • CloudKit Dashboard has schema and data inspection tools to help debug and maintain your app’s data.
  • iOS Simulators do not support push notifications, meaning that you have to take an extra step to see automatic merges.
  • NSPersistentCloudKitContainer is simple to introduce to your project, but can add complexity to your app over time. Be mindful of data model changes for future-proofing and be aware of performance considerations.

Where to go from here?

Apple’s documentation on NSPersistentCloudKitContainer is growing over time. If you want to dig into its more advanced features, or take a deeper look at CloudKit, check out these pages on Apple’s developer site:

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.

Unlock now