Article

Setting Up Core Data with CloudKit

Set up the classes and capabilities that sync your store to CloudKit.

Overview

With minimal setup, you can begin using Core Data with CloudKit in a new or existing Xcode project. To get started, you turn on a couple of capabilities and modify the standard Core Data stack setup to use an NSPersistentCloudKitContainer.

For more information about requirements, see Mirroring a Core Data Store with CloudKit.

Configure a New Xcode Project

In Xcode, select File > New > Project. Select one of the following templates.

  • iOS Single View App

  • iOS Master-Detail App

  • tvOS Single View App

  • macOS Cocoa App

In the dialog for creating a new project, select the Use Core Data and Use CloudKit checkboxes.

Screenshot showing the new project creation dialog with the Use Core Data and Use CloudKit checkboxes selected.

The resulting project instantiates an NSPersistentCloudKitContainer in your app’s delegate. NSPersistentCloudKitContainer is a subclass of NSPersistentContainer with the ability to synchronize a local persistent store to CloudKit.

Enable iCloud, Push Notification, and Background Modes Capabilities

In the Project Settings, select the Signing & Capabilities tab. Make sure that “Automatically manage signing” is selected, and specify your development team.

Screenshot showing Add Capability button in Signing & Capabilities tab of the project settings.

Click the + Capability button to open the Add Capability editor. In the search bar, type iCloud to filter the list, and choose the iCloud capability.

Screenshot showing the Add Capability editor with a search bar at the top, and a list of capabilities below.

An iCloud section appears on your app’s Signing & Capabilities page. Under Services, select the checkbox to enable CloudKit. Under Containers, leave the selection as “Use default container.”

Screenshot showing the iCloud section of the Signing & Capabilities tab with CloudKit and Use Default Container selected.

Selecting the CloudKit service enables your app to use CloudKit, and adds the push notifications capability. Push notifications allow CloudKit to notify your app when remote data has changed.

Xcode attempts to register your app’s bundle identifier and manage provisioning profiles. For more information about working with CloudKit containers and setting up profiles, see Enabling CloudKit in Your App.

Finally, add the Background Modes capability, and select the “Remote notifications” checkbox.

Screenshot showing the Background Modes section of the Signing & Capabilities tab with the Remote notifications checkbox selected.

Because remote notifications happen silently in the background, user approval isn’t required and no dialog displays to the user.

Update an Existing Xcode Project

In an existing project, replace your persistent container with an instance of NSPersistentCloudKitContainer when setting up the Core Data stack.

For example, if you create a project from the iOS Single View App template, with the Use Core Data checkbox selected, the following code will appear in your app’s delegate.

class AppDelegate: UIResponder, UIApplicationDelegate {

    // ...
    
    lazy var persistentContainer: NSPersistentContainer = {
    
        let container = NSPersistentContainer(name: "Earthquakes")
        container.loadPersistentStores(completionHandler: { 
            (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()
    
    // ...
}

Replace the NSPersistentContainer with an NSPersistentCloudKitContainer.

    let container = NSPersistentCloudKitContainer(name: "Earthquakes")

NSPersistentCloudKitContainer is a subclass of NSPersistentContainer with the ability to synchronize a local persistent store to CloudKit.

For more information about working with NSPersistentContainer, see Setting Up a Core Data Stack.

Manage Multiple Stores

You can add configurations in your data model to separate entities into discrete stores. This separation enables you to designate a subset of the data to store in the cloud, while keeping other data local to the device.

Add a configuration to your project’s .xcdatamodeld file by selecting Editor > Add Configuration, and drag and drop each entity into a configuration.

Screenshot showing the .xcdatamodeld file with the Configuration list at left containing Default, Cache, Cloud, and Local configurations. The Cloud configuration is selected and its “Used with CloudKit” checkbox is selected in the Data Model inspector.

For each configuration that should synchronize to CloudKit, select the configuration. In the data model editor, select the “Used with CloudKit” checkbox.

When working with a single store, the persistent CloudKit container matches the first store description with the first CloudKit container identifier in the entitlements.

When working with multiple stores, create an instance of NSPersistentCloudKitContainerOptions for each store you wish to use with CloudKit. Use it to set the cloudKitContainerOptions on the relevant store description.

For example, the following code creates two store descriptions: one for the “Local” configuration, and one for the “Cloud” configuration. It then sets the cloud store description’s cloudKitContainerOptions to match the store with its CloudKit container. Finally, it updates the container’s list of persistent store descriptions to include all local and cloud-backed store descriptions, and loads both stores.

lazy var persistentContainer: NSPersistentCloudKitContainer = {
    let container = NSPersistentCloudKitContainer(name: "Earthquakes")
    
    // Create a store description for a local store
    let localStoreLocation = URL(fileURLWithPath: "/path/to/local.store")
    let localStoreDescription =
        NSPersistentStoreDescription(url: localStoreLocation)
    localStoreDescription.configuration = "Local"
    
    // Create a store descpription for a CloudKit-backed local store
    let cloudStoreLocation = URL(fileURLWithPath: "/path/to/cloud.store")
    let cloudStoreDescription =
        NSPersistentStoreDescription(url: cloudStoreLocation)
    cloudStoreDescription.configuration = "Cloud"

    // Set the container options on the cloud store
    cloudStoreDescription.cloudKitContainerOptions = 
        NSPersistentCloudKitContainerOptions(
            containerIdentifier: "com.my.container")
    
    // Update the container's list of store descriptions
    container.persistentStoreDescriptions = [
        cloudStoreDescription,
        localStoreDescription
    ]
    
    // Load both stores
    container.loadPersistentStores { storeDescription, error in
        guard error == nil else {
            fatalError("Could not load persistent stores. \(error!)")
        }
    }
    
    return container
}()

See Also

Configuring CloudKit Mirroring

Creating a Core Data Model for CloudKit

Design a CloudKit-compatible data model and initialize your CloudKit schema.

Syncing a Core Data Store with CloudKit

Synchronize objects between devices, and handle store changes in the user interface.

Reading CloudKit Records for Core Data

Access CloudKit records created from Core Data managed objects.