Skip to content

Instantly share code, notes, and snippets.

@keith
Last active August 11, 2017 17:57
Show Gist options
  • Save keith/3717077 to your computer and use it in GitHub Desktop.
Save keith/3717077 to your computer and use it in GitHub Desktop.
Some code for dealing with replacing pre-populated Core Data databases that are subject to change version by version. Place this in your `- (NSPersistentStoreCoordinator *)persistentStoreCoordinator` method.
// Main database location
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"<#(DatabaseNameAndType)#>"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// The Build/Bundle Version number of the application on launch
NSString *versionNumber = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleVersionKey];
// Instead of using your app's bundle version create a custom key in your Info.plist for the database version. This is probably a better idea
// NSString *versionNumber = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"DatabaseVersion"];
// Get newest stored version from NSUserDefaults
NSString *newestNumber = [prefs stringForKey:NEWEST_RAN_VERSION];
// Check if either the database doesn't exist or if the application is a newer version than the previously stored version
if (![fileManager fileExistsAtPath:[storeURL path]] || ![newestNumber isEqualToString:versionNumber]) {
// Get the database stored within your application's bundle
NSString *bundledStorePath = [[NSBundle mainBundle] pathForResource:@"<#(BundledDatabaseName)#>" ofType:@"<#(BundledDatabaseType)#>"];
if ([fileManager fileExistsAtPath:bundledStorePath]) { // If bundled database exists
// Name of backup database and temporary backup database
NSURL *backupStoreURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"<#(BackupDatabaseNameAndType)#>"];
NSURL *secondBackupStoreURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"<#(TemporaryBackupDatabaseNameAndType)#>"];
if ([fileManager fileExistsAtPath:[backupStoreURL path]]) {
NSError *movedOldBackupError = nil;
// Move database backup to temporary location. You may not want to do this depending on your database's size
BOOL movedOldBackup = [fileManager moveItemAtURL:backupStoreURL toURL:secondBackupStoreURL error:&movedOldBackupError];
if (!movedOldBackup) {
NSLog(@"Failed to backup %@", [movedOldBackupError localizedDescription]);
}
}
// Check if main database already exists
if ([fileManager fileExistsAtPath:[storeURL path]]) {
NSError *backupError = nil;
// Backup main database to default backup location
BOOL backedUp = [fileManager moveItemAtURL:storeURL toURL:backupStoreURL error:&backupError];
if (backedUp) {
if (![fileManager fileExistsAtPath:[storeURL path]]) {
NSLog(@"database moved successfully");
// If the second backup exists, remove it
if ([fileManager fileExistsAtPath:[secondBackupStoreURL path]]) {
// If the database was backed up sucessfully remove the temporary backup
NSError *removedSecondBackupError = nil;
BOOL removedSecondBackup = [fileManager removeItemAtURL:secondBackupStoreURL error:&removedSecondBackupError];
if (!removedSecondBackup) {
NSLog(@"Failed to remove temporary backup %@", [removedSecondBackupError localizedDescription]);
}
}
}
} else {
NSLog(@"Database backup failed %@", [backupError localizedDescription]);
}
}
// Copy bundled database to the default location
NSError *error = nil;
BOOL copied = [fileManager copyItemAtPath:bundledStorePath toPath:[storeURL path] error:&error];
if (copied) {
// Set newest version number to NSUserDefaults
NSLog(@"Copied new database");
[prefs setValue:versionNumber forKey:NEWEST_RAN_VERSION];
[prefs synchronize];
} else {
NSLog(@"Copy database error %@", [error localizedDescription]);
// If database failed to copy attempt to copy the backup database to default location
if ([fileManager fileExistsAtPath:[backupStoreURL path]]) {
NSError *moveOldDatabaseError = nil;
BOOL movedOldDatabase = [fileManager copyItemAtURL:backupStoreURL toURL:storeURL error:&moveOldDatabaseError];
if (movedOldDatabase) {
NSLog(@"Copied old database to default location");
} else {
// No database exists. Epic fail.
NSLog(@"Failed to copy old database %@", [moveOldDatabaseError localizedDescription]);
#warning Refrain from using `abort();` in production level code (says Apple)
abort();
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment