Hi, I've been working on an app that - so far - has only had to deal with offline data store.
The usage is fairly simple: the user picks their favourite tv shows and networks, and they get persisted with SwiftData with all the correct relationships.
Now, I would like to migrate the local storage of the users to a private CloudKit db, but every time I upgrade the app, the data seems to disappear completely.
This is the snippet evolved through the attempt of migrating the data:
Current Production code
public static func makeModelContainer() -> ModelContainer {
do {
let processRequiresInMemory = ProcessInfo.processInfo.arguments.contains("inMemoryDatabasePreferred")
let modelConfiguration = ModelConfiguration(
isStoredInMemoryOnly: processRequiresInMemory,
groupContainer: .automatic,
cloudKitDatabase: .none
)
let modelContainer = try ModelContainer(
for: Country.self,
Episode.self,
Movie.self,
Season.self,
Show.self,
Network.self,
NetworkSubscription.self,
migrationPlan: AppModelMigrationPlan.self,
configurations: modelConfiguration
)
return modelContainer
} catch {
fatalError("Could not initialize model container")
}
}
Testing CloudKit enabled
public static func makeModelContainer() -> ModelContainer {
do {
let processRequiresInMemory = ProcessInfo.processInfo.arguments.contains("inMemoryDatabasePreferred")
let modelConfiguration = ModelConfiguration(
"synced",
isStoredInMemoryOnly: processRequiresInMemory,
groupContainer: .automatic,
cloudKitDatabase: .automatic
)
let modelContainer = try ModelContainer(
for: Country.self,
Episode.self,
Movie.self,
Season.self,
Show.self,
Network.self,
NetworkSubscription.self,
migrationPlan: AppModelMigrationPlan.self,
configurations: modelConfiguration
)
return modelContainer
} catch {
fatalError("Could not initialize model container")
}
}
}
The differences, which I don't understand fully because I could not find documentation, are:
ModelContainer(...)
->ModelContainer("synced", ...)
- cloudKitDatabase, from
none
toautomatic
.
I have the feeling that changing the name of the configuration also changes some reference to the db itself, but if I were not to change the name, the app would have crashed because unable to migrate.
What's the best approach to take here?
Unresolved error loading container Error Domain=NSCocoaErrorDomain Code=134060 "A Core Data error occurred." UserInfo={NSLocalizedFailureReason=Unable to find a configuration named 'default' in the specified managed object model.}
It seems that you are hitting a SwiftData bug – When CloudKit integration is enabled, creating a ModelContainer
with a migration plan triggers an error.
Since WWDC is there, I'd suggest that you try with the latest beta. If the issue is still there, please file a feedback report for the SwiftData team to investigate.
For an immediate workaround, you might consider the following flow:
-
Create two model containers, container1 for the local store and container2 for the CloudKit store. For container2, use a configuration name ("synced" in your case) to differentiate the CloudKit store from the local one, and don't use migration plan, which avoids the error.
-
Migrate the data with your own code, which includes fetching data from container1, transforming it if necessary, and saving the transformed data to container2. The data should then be synchronized to CloudKit.
-
After the data is all added to container2, you can release container1, and remove the local store.
Best,
——
Ziqiao Chen
Worldwide Developer Relations.