Using SwiftData with a local and CloudKit backed configuration at the same time

I'm trying to set up an application using SwiftData to have a number of models backed by a local datastore that's not synced to CloudKit, and another set of models that is. I was able to achieve this previously with Core Data using multiple NSPersistentStoreDescription instances.

The set up code looks something like:

    do {
      let fullSchema = Schema([
        UnsyncedModel.self,
        SyncedModel.self,
      ])

      let localSchema = Schema([UnsyncedModel.self])
      let localConfig = ModelConfiguration(schema: localSchema, cloudKitDatabase: .none)

      let remoteSchema = Schema([SyncedModel.self])
      let remoteConfig = ModelConfiguration(schema: remoteSchema, cloudKitDatabase: .automatic)

      container = try ModelContainer(for: fullSchema, configurations: localConfig, remoteConfig)
    } catch {
      fatalError("Failed to configure SwiftData container.")
    }

However, it doesn't seem to work as expected. If I remove the synced/remote schema and configuration then everything works fine, but the moment I add in the remote schema and configuration I get various different application crashes. Some examples below:

A Core Data error occurred." UserInfo={Reason=Entity named:... not found for relationship named:...,
Fatal error: Failed to identify a store that can hold instances of SwiftData._KKMDBackingData<...>

Has anyone ever been able to get a similar setup to work using SwiftData?

Answered by DTS Engineer in 861310022

Thanks for providing the project. The issue happens because you don't specify a name for your model configurations.

When using multiple configurations, give each configuration a unique name so SwiftData knows how to separate the data and schema.

The following code fixes the issue:

let fullSchema = Schema([
  LocalModel.self,
  RemoteModel.self,
])
let localSchema = Schema([LocalModel.self])
let localConfig = ModelConfiguration("Local", schema: localSchema, cloudKitDatabase: .none)
let remoteSchema = Schema([RemoteModel.self])
let remoteConfig = ModelConfiguration("Remote", schema: remoteSchema, cloudKitDatabase: .automatic)
container = try ModelContainer(for: fullSchema, configurations: localConfig, remoteConfig)

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Your code doesn't provide the details of UnsyncedModel and SyncedModel, and so I am wondering if there is any connection between the two models. Do you have a minimal project that reproduces the issue? If you can share one, I'll find time to take a look.

Also did you try with two model containers, one for the local store, and the other for the CloudKit store? When one container with two configurations doesn't work, that may be the solution.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Hi,

Thank you very much, I've pushed a minimal project which fails to GitHub: https://github.com/thomasleese/swiftdata-local-and-remote-sample

If you run it, you should find the following error:

SwiftData/ModelContext.swift:3699: Fatal error: Failed to identify a store that can hold instances of SwiftData._KKMDBackingData<SwiftDataLocalRemoteSample.LocalModel> from ["8B7D97A6-4C92-49AD-9C78-17D04917B135": SwiftData.DefaultStore]

I haven't tried yet with two separate model containers, although I think this will be tricky because a lot of the views requires a combination of models from both stores.

Thanks for providing the project. The issue happens because you don't specify a name for your model configurations.

When using multiple configurations, give each configuration a unique name so SwiftData knows how to separate the data and schema.

The following code fixes the issue:

let fullSchema = Schema([
  LocalModel.self,
  RemoteModel.self,
])
let localSchema = Schema([LocalModel.self])
let localConfig = ModelConfiguration("Local", schema: localSchema, cloudKitDatabase: .none)
let remoteSchema = Schema([RemoteModel.self])
let remoteConfig = ModelConfiguration("Remote", schema: remoteSchema, cloudKitDatabase: .automatic)
container = try ModelContainer(for: fullSchema, configurations: localConfig, remoteConfig)

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Using SwiftData with a local and CloudKit backed configuration at the same time
 
 
Q