6
votes

I made an iOS 8 app that uses the new app groups feature to share a Core Data store with an extension. It worked so well that I thought I would try it with 2 separate apps sharing a Core Data store in an App Group container. But while it worked between App and Extension, I am getting Core Data store corruptions issues when sharing with 2 apps.

Depending on the order in which I open the 2 apps, I get different errors:

Fetches cause this error:

CoreData: error: (522) I/O error for database at /private/var/mobile/Containers/Shared/AppGroup/[…].sqlite. SQLite error code:522, 'not an error’

Saves cause this error:

CoreData: error: (11) Fatal error. The database at /private/var/mobile/Containers/Shared/AppGroup/[...].sqlite is corrupted. SQLite error code:11, 'database disk image is malformed’

Or:

Core Data: error: -executeRequest: encountered exception = error during SQL execution : PRIMARY KEY must be unique with userInfo = { NSFilePath = "/private/var/mobile/Containers/Shared/AppGroup/[...].sqlite"; NSSQLiteErrorDomain = 19; } CoreData: error: (19) PRIMARY KEY must be unique

1
Would be interested to know this myself (if it's possible at all). You'll definitely have to implement some versioning system so that if the database is upgraded by one app any other apps that access the database do not connect until they understand that database version.Robotic Cat
@RoboticCat, yeah I thought of that issue with versioning. But since I can't even get them to work on the same version, I'm in trouble :)Richard Venable
Did you solve this? Having the same issue.Claes

1 Answers

0
votes

Here's how I did it by creating a framework to hold/manage the database

  1. Add the same entry to your App Groups entitlements in each of your apps
  2. Use it to create your databaseURL using:

    [NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:

  3. database = [ [UIManagedDocument alloc] initWithFileURL: databaseURL]

  4. [database saveToFileURL: database.fileURL forSaveOperation: UIDocumentSaveForCreating completionHandler: ^(BOOL success)
  5. If successful, initialize the persistentContainer.
  6. Now here's the tricky part... the managedObjectModel has to be defined by the framework. It cannot be in any of the apps. They can see it, but it has to be part of the framework's bundle. That's the basic outline and there is a lot more to it, but with this you should be able to get there. Have fun!