3

I am trying to move my NSPersistentStore from my app's sandbox to a shared group container so I can access CoreData from my WatchKit extension. I am currently using Core Data with iCloud and want to move the users data to the shared group container. Currently I am creating the NSPersistentStoreCoordinator as follows:

if (__persistentStoreCoordinator != nil) {
    return __persistentStoreCoordinator;
}

NSURL *url = [self storeURL]; // app's Documents directory
NSError *error = nil;
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:[self iCloudPersistentStoreOptions] error:&error]) {
    NSLog(@"Error adding persistent store: %@", [error localizedDescription]);
}

// rest of setup

return __persistentStoreCoordinator;

I've already setup the shared group container in my app target and WatchKit extension target and can get the NSURL for the new store location using - (NSURL *)containerURLForSecurityApplicationGroupIdentifier:(NSString *)groupIdentifier.

How can I check whether I need to migrate or that I've already migrated so I don't attempt to migrate multiple times? Initially I was thinking of something like this, but this doesn't work as the old store URL doesn't exist

if (__persistentStoreCoordinator != nil) {
    return __persistentStoreCoordinator;
}

NSURL *newURL = [self newStoreURL]; // shared group container
NSURL *oldURL = [self oldStoreURL]; // app's Documents directory

__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

NSFileManager *fileManager = [NSFileManager defaultManager];

if (![fileManager fileExistsAtPath:newURL.path] && [fileManager fileExistsAtPath:oldURL.path]) {
    NSLog(@"performing migration...");
    NSPersistentStore *oldStore = [__persistentStoreCoordinator persistentStoreForURL:oldURL];
    NSError *migrateError = nil;
    NSPersistentStore *newStore = [__persistentStoreCoordinator migratePersistentStore:oldStore toURL:newURL options:[self iCloudPersistentStoreOptions] withType:NSSQLiteStoreType error:&migrateError];
    if (!newStore) {
        NSLog(@"Error migrating store: %@", [migrateError localizedDescription]);
    }
}

// rest of setup

return __persistentStoreCoordinator;
rick
  • 100
  • 7

1 Answers1

1

From what I can tell, it looks like you're pretty much there if the migration logic you posted is working. What it seems you are missing is an else if to handle the case where you don't have a persistent store. The following should handle that case.

if (__persistentStoreCoordinator != nil) {
    return __persistentStoreCoordinator;
}

NSURL *newURL = [self newStoreURL]; // shared group container
NSURL *oldURL = [self oldStoreURL]; // app's Documents directory

__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

NSFileManager *fileManager = [NSFileManager defaultManager];

if (![fileManager fileExistsAtPath:newURL.path] && [fileManager fileExistsAtPath:oldURL.path]) {
    NSLog(@"performing migration...");
    NSPersistentStore *oldStore = [__persistentStoreCoordinator persistentStoreForURL:oldURL];
    NSError *migrateError = nil;
    NSPersistentStore *newStore = [__persistentStoreCoordinator migratePersistentStore:oldStore toURL:newURL options:[self iCloudPersistentStoreOptions] withType:NSSQLiteStoreType error:&migrateError];
    if (!newStore) {
        NSLog(@"Error migrating store: %@", [migrateError localizedDescription]);
    }
} else if (![fileManager fileExistsAtPath:newURL.path]) {
    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:newURL options:[self iCloudPersistentStoreOptions] error:&error]) {
        NSLog(@"Error adding persistent store: %@", [error localizedDescription]);
    }
}

// rest of setup

return __persistentStoreCoordinator;
cnoon
  • 16,575
  • 7
  • 58
  • 66
  • The problem is that with existing installs (users who are upgrading and already have data), [NSFileManager fileExistsAtPath:oldURL.path] returns false for some reason. – rick Feb 26 '15 at 17:45
  • 1
    The actual store file in my case is actually in the Documents/CoreDataUbiquitySupport///local/store directory which is why [NSFileManager fileExistsAtPath:oldURL.path] is returning false – rick Feb 26 '15 at 22:04