Accessing Core Data SQL Database in iOS 8 Extension (Sharing Data Between App and Widget Extension)

Mark Bridges picture Mark Bridges · Jul 8, 2014 · Viewed 16.3k times · Source

Problem:

Unable to access application's Core Data database from within a Widget Extension in the Today View.

The app itself is able to read and write to the database as per normal under iOS 8, but the extension will fail to create the store, giving the error, unable to write to file.

The log is the following:

Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be completed. (Cocoa error 512.)"

reason = "Failed to create file; code = 2

Answer

Mark Bridges picture Mark Bridges · Jul 8, 2014

Widgets are unable to access the NSDocuments directory, which is where one would normally store their database.

The solution is to first create an App Group

Go to: Project - Target - App Groups - Add New Container

Name the container, i.e. 'group.mycontainer'

Repeat the process for the Widget's Target using the same name for the container.

Then write your database to your group container.

So:

NSURL *storeURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory  inDomains:NSAllDomainsMask] lastObject];
storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];

Becomes:

NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.mycontainer"];
storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];

And initialising the store should be like so:

NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.mycontainer"];
storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];

NSPersistentStore *store = nil;
store = [coordinator addPersistentStoreWithType:NSSQLiteStoreType
                                  configuration:nil
                                            URL:storeURL
                                        options:nil
                                          error:&error]