-->

Core Data and iCloud adding Pre-Populated sqlite f

2020-07-30 06:13发布

问题:

I'm working on an app that uses Core Data and iCloud to sync data between multiple iPads. This is all working fine and I can add data to each iPad and it will sync between them all.

I have a Core Data sqlite file that is pre-populated with a list of countries and I want to copy this to the documents area on first run of the app. I had this working but have changed my persistentStoreCoordinator implementation to test for iCloud support or not and a couple of other small changes.

However now when I check to see if the sqlite file exists and copy the pre-populated sqlite file if it doesn't I get the following error at

[psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:iCloudData] options:options error:&persistentStoreError];

NSPersistentStoreCoordinator addPersistentStoreWithType:configuration:URL:options:error:: CoreData: Ubiquity: An error occured while setting up the ubiquity integration: Error Domain=NSCocoaErrorDomain Code=134316 "The ubiquity container does not appear to match this persistent store, it is possible this is caused by switching to a different iCloud account, or logging out of iCloud entirely. The store should be re-opened with read-only attributes or removed from iCloud syncing permanently." UserInfo=0x1cb590 {storeUUID=31381598-EAFA-4550-9B96-F501800974D5, containerUUID=E3A8DC7D-41FD-405A-8D8A-C06C8B467CA2, NSLocalizedDescription=The ubiquity container does not appear to match this persistent store, it is possible this is caused by switching to a different iCloud account, or logging out of iCloud entirely. The store should be re-opened with read-only attributes or removed from iCloud syncing permanently.}

Is this because there are still references in iCloud to a different Core Data sqlite file or transaction log files? If so how would I remove them?

回答1:

You're not supposed to copy a pre-created Core Data store to the ubiquity container. The old way to do this was to create an SQLite file on the Simulator/device/computer and copy it into it's place on first run. If you use iCloud, you can't do this any more. iCloud works by each device receiving a list of changes as "transaction logs", which it then applies to it's own SQLite store. It needs to know what's changed, and getting a .sqlite file in one lump won't tell it that.

The iCloud way to do this is either:

  • Create the initial data from inside your code (e.g. an insertStartData: method). You could add it from a plist, or whatever you like. You'll have to check that the data isn't already there first.
  • Use NSPersistentStoreCoordinator's migratePersistentStore:toURL:options:withType:error to copy your initial store across.

Here's the docs:

You should not seed initial content with a prepackaged database file. Instead, you should create the default items in code, or use NSPersistentStoreCoordinator's migratePersistentStore:toURL:options:withType:error: method to migrate a prepackaged database to the required location.