Search code examples
objective-ccocoacore-datacore-data-migration

Where to Put Code Configuring Persistent Store for Migration


I have a Mac App already created and distributed on the App Store to many customers, and I need to add an attribute to the Core Data Model. I read the documentation provided by Apple, available here.

However, it gives this block of code to enable automatic migration:

NSError *error;
NSPersistentStoreCoordinator *psc = <#The coordinator#>;
NSURL *storeURL = <#The URL of a persistent store#>;
NSDictionary *optionsDictionary =
    [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                    forKey:NSMigratePersistentStoresAutomaticallyOption];

NSPersistentStore *store = [psc addPersistentStoreWithType:<#Store type#>
                                configuration:<#Configuration or nil#>
                                URL:storeURL
                                options:optionsDictionary
                                error:&error];

.. And I have no idea where to put that. Someone mentioned (in another thread) that it goes into a PersistentStoreCoordinator, however, I simply used the default Cocoa App Template with "Use Core Data for Storage" enabled. I had to create my own AppDelegate and never saw anything about a PersistentStoreCoordinator (and still don't. I've tried creating a new app just to check). Any help here? I'm new to Cocoa but my app works perfectly fine without a PersistentStoreCoordinator, which is why I haven't implemented one yet.. I do have an AppDelegate I created, but when I put this code in there it throws many errors. HELP :/

EDIT (for nick): Here is the new code: enter image description here

And my header file: enter image description here


Solution

  • Here you go: Core Data relevant header and methods.

    Application Delegate Header - Core Data relevant parts

    @interface CoreDataFirstStepsAppDelegate : NSObject <UIApplicationDelegate> 
    {    
         // ...
    @private
        NSManagedObjectContext *managedObjectContext_;
        NSManagedObjectModel *managedObjectModel_;
        NSPersistentStoreCoordinator *persistentStoreCoordinator_;
    }
    
    // ...
    
    @property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
    @property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
    @property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
    

    Application Delegate Implementation - Core Data relevant parts

    /**
     Returns the managed object context for the application.
     If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
     */
    - (NSManagedObjectContext *)managedObjectContext {
    
        if (managedObjectContext_ != nil) {
            return managedObjectContext_;
        }
    
        NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
        if (coordinator != nil) {
            managedObjectContext_ = [[NSManagedObjectContext alloc] init];
            [managedObjectContext_ setPersistentStoreCoordinator:coordinator];
        }
        return managedObjectContext_;
    }
    
    
    /**
     Returns the managed object model for the application.
     If the model doesn't already exist, it is created from the application's model.
     */
    - (NSManagedObjectModel *)managedObjectModel {
    
        if (managedObjectModel_ != nil) {
            return managedObjectModel_;
        }
        NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"CoreDataFirstSteps" ofType:@"momd"];
        NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
        managedObjectModel_ = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];    
        return managedObjectModel_;
    }
    
    
    /**
     Returns the persistent store coordinator for the application.
     If the coordinator doesn't already exist, it is created and the application's store added to it.
     */
    - (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    
        if (persistentStoreCoordinator_ != nil) {
            return persistentStoreCoordinator_;
        }
    
        NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataFirstSteps.sqlite"];
    
        NSError *error = nil;
        persistentStoreCoordinator_ = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
        if (![persistentStoreCoordinator_ addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
    
            NSError *error;
            NSURL *storeURL = storeURL;
            NSPersistentStoreCoordinator *psc = persistentStoreCoordinator_;
            NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                                     [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                                     [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
    
            if (![psc addPersistentStoreWithType:NSSQLiteStoreType
                                   configuration:nil
                                             URL:storeURL
                                         options:options 
                                           error:&error]) 
            {
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }       
        }    
    
        return persistentStoreCoordinator_;
    }
    
    /**
     Returns the URL to the application's Documents directory.
     */
    - (NSURL *)applicationDocumentsDirectory {
        return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    }