8

When compiling and running in the XCode a project using Core Data I'm getting an error I never saw before:

 2013-09-12 16:59:10.156 myapp[57811:70b] CoreData: error: 
      (14) I/O error for database at /Users/administrador/Library/
         Application Support/iPhone Simulator/7.0/Applications/
         6BA67336-B093-46CF-8B11-E3595409DAC2/myapp.app/database.sqlite.  

         SQLite error code:14, 'unable to open database file'

The code that generates this message is:

    psc = [[NSPersistentStoreCoordinator alloc]
                   initWithManagedObjectModel:self.managedObjectModel];
    NSURL *storeURL = [[NSBundle mainBundle] 
                         URLForResource:@"database" withExtension:@"sqlite"];
    [psc addPersistentStoreWithType:NSSQLiteStoreType 
             configuration:nil URL:storeURL 
             options:@{NSReadOnlyPersistentStoreOption : @YES} error:NULL];

I have tried Build->Clean, remove derived data, uninstall the app.

I have checked this question before posting and I believe the problem is different.

Note: The sqlite is a resource of the app

The info using the debug suggested

2013-09-12 17:43:38.341 myapp[58322:70b] CoreData: annotation: Connecting to sqlite database file at "/Users/administrador/Library/Application Support/iPhone Simulator/7.0/Applications/6BA67336-B093-46CF-8B11-E3595409DAC2/myapp.app/database.sqlite"
2013-09-12 17:43:38.360 myapp[58322:70b] CoreData: sql: SELECT Z_VERSION, Z_UUID, Z_PLIST FROM Z_METADATA
2013-09-12 17:43:38.363 myapp[58322:70b] CoreData: annotation: Disconnecting from sqlite database due to an error.
2013-09-12 17:43:38.364 myapp[58322:70b] CoreData: error: (14) I/O error for database at /Users/administrador/Library/Application Support/iPhone Simulator/7.0/Applications/6BA67336-B093-46CF-8B11-E3595409DAC2/myapp.app/database.sqlite.  SQLite error code:14, 'unable to open database file'
2013-09-12 17:43:38.366 myapp[58322:70b] CoreData: annotation: Disconnecting from sqlite database.
Community
  • 1
  • 1
ppaulojr
  • 3,579
  • 4
  • 29
  • 56

2 Answers2

6

Now that the NDA on iOS7 has been lifted I can post for the sake of completion the workaround I found for this problem.

The Core Data in iOS7 uses by default WAL in the sqlite.

The only solution that did work was to create the sqlite using iOS6 simulator without WAL and import it in the project:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    static NSPersistentStoreCoordinator *psc;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        psc = [[NSPersistentStoreCoordinator alloc] 
                 initWithManagedObjectModel:self.managedObjectModel];
        NSURL *storeURL = [[NSBundle mainBundle] 
                  URLForResource:@"database" withExtension:@"sqlite"];
        [psc addPersistentStoreWithType:NSSQLiteStoreType
                          configuration:nil
                                    URL:storeURL
                                options:@{NSReadOnlyPersistentStoreOption : @YES,
                             NSSQLitePragmasOption: @{@"journal_mode":@"DELETE"}}
                                  error:NULL];
    });
    return psc;
}
ppaulojr
  • 3,579
  • 4
  • 29
  • 56
  • It's easier to just disable WAL like here: http://stackoverflow.com/a/18870738/288860 – mclin Mar 23 '14 at 05:45
  • Thanks a lot for this, was looking for a solution online for ages. It's so frustrating that documentation for using a prepopulated read-only db in IOS is so lacking. – user1785227 Oct 30 '15 at 13:11
3
NSURL *storeURL = [[NSBundle mainBundle] 
                     URLForResource:@"database" withExtension:@"sqlite"];

builds a path inside the application bundle, which is read-only. The persistent store file needs to reside in a writable directory, e.g. the "Documents" directory.

EDIT: The above answer is actually wrong, it is possible to open a read-only Core Data file from the application bundle (using NSReadOnlyPersistentStoreOption). The only thing I can currently imagine is that the bundled file is not a valid Core Data database. Adding the launch argument

-com.apple.CoreData.SQLDebug 1

might help to localize the problem.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Though you're probably right, it *is* unusual that it's not able to open a read-only database from a read-only location. – cutsoy Sep 12 '13 at 20:23
  • 1
    It always worked. I'm not sure why a read-only database must reside in Documents – ppaulojr Sep 12 '13 at 20:25
  • @ppaulojr: You are right (and I wrote this answer too quickly :-) - Could it be that the bundled file is not a valid Core Data database (matching the current model)? – Martin R Sep 12 '13 at 20:33
  • @ppaulojr: Perhaps add the launch argument "-com.apple.CoreData.SQLDebug 1" for more information. – Martin R Sep 12 '13 at 20:35
  • I added the info from `SQLDebug` – ppaulojr Sep 12 '13 at 20:49
  • @ppaulojr: Does it work if you copy the sqlite file to the Documents directory and open it from there? Can you open the file with the "sqlite3" command line tool? Does the problem occur on iOS 6 as well? – Martin R Sep 12 '13 at 20:54
  • it doesn't happen in iOS6 – ppaulojr Sep 12 '13 at 21:10
  • @ppaulojr: (This is just an idea!) Have a look at the "What’s New in Core Data and iCloud" session from WWDC 2013. You can download the PDF file from https://developer.apple.com/wwdc/videos/. Apple changed the default journaling mode for the SQLite file from "rollback" to "write-ahead logging". This should not matter for a read-only file, but on page 177 of that PDF file you see a option to restore the old behavior. You could try if that helps. – Martin R Sep 12 '13 at 21:27
  • I'll take a look and maybe we should hold the answer until 17th Sept. – ppaulojr Sep 12 '13 at 21:41
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/37288/discussion-between-martin-r-and-ppaulojr) – Martin R Sep 12 '13 at 21:41