How to avoid WAL files in Core Data

Since iOS 7 and OS X 10.9 the default journalling mode in SQLite Stores is WAL. In addition to the main store file you’ll find a WAL file with the same (or larger) size as the store file, and a less important SHM file.

Prior to this implementation it was easy to save the context, extract the store file and ship it with an app as a pre-made data store. That’s no longer possible, because by default all data changes are written to the WAL file and do not sync with the main store file.

This is not a problem if you’re not shipping a pre-made store file with your app, but if you do, then this “improvement” has just ruined your way of delivering prewritten data stores.

Lucky for us we can switch this entire WAL business off by passing an option when creating our NSPersistentStoreCoordinator:

@{NSSQLitePragmasOption: @{@"journal_mode": @"delete"}}

This bizarre brackety @-intense statement is shorthand for an NSDictionary within a dictionary. Not so pretty on its own. In context, this statement can be passed as part of a default Core Data app when created from a template:

if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error]) {
    [[NSApplication sharedApplication] presentError:error];
    return nil;
}

No options are passed by default. The same statement amended with the no-WAL option would look like this:

if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:@{NSSQLitePragmasOption: @{@"journal_mode": @"delete"} error:&error]) {
    [[NSApplication sharedApplication] presentError:error];
    return nil;
}

In addition you can pass other options like so:

if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:@{NSSQLitePragmasOption: @{@"journal_mode": @"delete"}, NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES} error:&error]) {
    [[NSApplication sharedApplication] presentError:error];
    return nil;
}

Adding this will do away with WAL and let you use your persistent store file on its own again. At the time of writing, I know of no way to sync the changes from the WAL file back into the main store file.





2 thoughts on “How to avoid WAL files in Core Data

Leave a Reply