2
votes

I have a app that is using core data. The Core Data stack (the context, object graph, persistent store coordinator, and the persistent store) is being created, and I am able to use it without issue. The problem is that the saved data is not persisting, can someone help me with what I am doing wrong? Here is where I create the Core Data stack.

- (void)initializeCoreDataStack
{
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Favorites"
                                              withExtension:@"momd"];
    if (!modelURL)
        NSLog(@"MODEL URL NOT INITIALIZED");

    NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    if (!mom)
        NSLog(@"OBJECT MODEL NOT CREATED");

    NSPersistentStoreCoordinator * psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
    if (!psc)
        NSLog(@"PERSISTENT STORE COORDINATOR NOT CREATED");

    NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    [moc setPersistentStoreCoordinator:psc];
    self.managedObjectContext = moc;

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
       NSArray *directory = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
                                                               inDomains:NSUserDomainMask];
        NSURL *storeUrl = [directory lastObject];
        storeUrl = [storeUrl URLByAppendingPathComponent:@"Favorites.sqlite"];

        NSError *error = nil;
        NSPersistentStore *store = [psc addPersistentStoreWithType:NSSQLiteStoreType
                                                     configuration:nil
                                                               URL:storeUrl
                                                           options:nil
                                                             error:&error];
        if (!store)
        {
            NSLog(@"ERROR CREATING STORE: %@ %@", error.localizedDescription, error.domain);
            // present error to user
        }
        else
        {
            dispatch_sync(dispatch_get_main_queue(), ^{
                // do something once the stack is finished being created
                NSLog(@"persistent store created");
            });
        }
    });
}
4
Do you ever call save on the context?borrrden

4 Answers

3
votes

You have to save core data explicitly, otherwise it won't persist. Not hard to solve, though.

In your controller implementation file (e.g. coreDataViewController.m), call this function when you want to save changes to core data

// add this call, whenever you want to save data
// e.g. responding to a UIButton event
[self saveCoreDataContext];

- (void)saveCoreDataContext
{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
}
1
votes

My personal experience is that, even if you called [moc save:error], you may not find the content saved while you are running the app from Xcode -> Build and Run on device. However, if you stop the Xcode from running the app, and launch the app from the device by clicking the App Icon, the content is actually persisted.

Just personal experience that I found through trial and error, hope that you see the same thing.

0
votes

You have to save the MOC.
[mom save:nil];

-1
votes

There's a few things here that stand out to me as odd. First, why are you threading the creation of the NSPersistentStore? Generally, I create the NSPersistentStoreCoordinator, add NSPersistentStores, and then create the contexts. I would suggest doing it in that order unless you have a good reason to do otherwise. While it's not specifically prohibited, you may experience problems adding a NSPersistentStore after the NSManagedObjectContext has been created.

I'm not sure if it is required or not, but I've always explicitly held a strong reference to the NSPersistentStoreCoordinator. It's useful to create multiple contexts, as well. I would suggest doing so in your code.

As everyone else has said, you also need to explicitly save.