Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8133195
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 6, 20262026-06-06T09:32:06+00:00 2026-06-06T09:32:06+00:00

I am trying to use Core Data in an app I’m working on; in

  • 0

I am trying to use Core Data in an app I’m working on; in the app delegate this code kicks off the import of data from a downloaded JSON file.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    //setup app window, etc.

    BECDRefreshOperation *loadData = [[BECDRefreshOperation alloc] initWithStoreCoordinator:self.persistentStoreCoordinator];

    [queue addOperation:loadData]; //queue is an NSOperationQueue

    return YES;

}

BECDRefreshOperation is a subclass of NSOperation that runs the import. It creates its own managed object context in order to separate the main one from the background process.

- (id) initWithStoreCoordinator:(NSPersistentStoreCoordinator *)storeCoordinator{
    if (![super init]) return nil;
    [self setPersistentStoreCoord:storeCoordinator];
    return self;
}

- (void) main{
    NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
    [f setNumberStyle:NSNumberFormatterDecimalStyle];

    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];

    [context setPersistentStoreCoordinator:self.persistentStoreCoord];

    //import the data from JSON

}

The actual import works and updates the data store; however, the table view controller which uses an NSFetchedResultsController does not update. The table view controller is the NSFetchedResultsControllerDelegate and contains all of the delegate methods.

On the second run of the app, the table view controller displays correctly because the data was previously loaded into the store; any updates made in the import do not refresh, however.

I have read the Core Data Concurrency guidelines from Apple multiple times as well as searched many times on Google and SO for the answer. I believe it lies in using mergeChangesFromContextDidSaveNotification, but I have tried to do this in many different places in both the app delegate and the table view controller by registering for the save notification and calling a method to merge changes, and none of what I have tried works. Cocoa is my GF’s implementation is one of the ways I have tried to adapt in order to do this.

The table view controller is passed the app delegate’s managedObjectContext when it is created.

I have run this without multithreading and the code to import into the data store and display in the table view controller works, but of course it freezes the UI while importing the data.

It’s pretty obvious I’m doing something wrong here; any help will be greatly appreciated.

Update
I added some NSLog statements and break points to see if the two managedObjectContexts were indeed pointing to the same memory address and it seems that they are, while the background MOC is at a different address. The notification code seems like it should work and update the main MOC, but thus far it is not.

2012-06-25 21:48:02.669 BE_CoreData[18113:13403] beerListViewController.managedObjectContext = <NSManagedObjectContext: 0x94233d0>
2012-06-25 21:48:02.671 BE_CoreData[18113:13403] appDelegate.managedObjectContext = <NSManagedObjectContext: 0x94233d0>
2012-06-25 21:48:02.722 BE_CoreData[18113:15003] backgroundMOC = <NSManagedObjectContext: 0x7b301b0>

Update 2 After additional troubleshooting it appears the NSFetchedController delegate methods are not firing. Here’s the code for the NSFetchedResultsController and its delegate.

- (NSFetchedResultsController *)fetchedResultsController {

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

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription
                                   entityForName:@"Beer" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    NSSortDescriptor *sort = [[NSSortDescriptor alloc]
                              initWithKey:@"beertitle" ascending:YES];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

    [fetchRequest setFetchBatchSize:20];

    NSFetchedResultsController *theFetchedResultsController =
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                        managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"beertitle"
                                                   cacheName:@"BeerTable"];
    _fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;

    return _fetchedResultsController;

}


- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    // The fetch controller is about to start sending change notifications, so prepare the table view for updates.
    [self.tableView beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [self.tableView deleteRowsAtIndexPaths:[NSArray
                                               arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [self.tableView insertRowsAtIndexPaths:[NSArray
                                               arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    // The fetch controller has sent all current change notifications, so tell the table view to process all updates.
    [self.tableView endUpdates];
}

Also here is the code for changeCell which is called when a cell needs updating:

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    Beer *beer = [_fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = beer.beertitle;

    if (beer.beerthumb != nil){
        [cell.imageView setImageWithURL:[NSURL URLWithString:beer.beerthumb]
                           placeholderImage:[UIImage imageNamed:@"placeholder.png"]];
    }
    else {
        [cell.imageView setImageWithURL:[NSURL URLWithString:@"http://beersandears.net/images/missing.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder.png"]];
    }

}

Finally the fetchBeers method is called by viewDidLoad to actually perform the fetch.

- (void)fetchBeers{

    NSError *error;
    if (![[self fetchedResultsController] performFetch:&error]) {
        // Update to handle the error appropriately.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    }
}

Update 3

Testing to ensure the fetch occurs first. It does, but not by much (this was run on a 4S).

2012-06-28 20:47:37.214 BE_CoreData[3559:907] Fetch called
2012-06-28 20:47:37.281 BE_CoreData[3559:1103] Import started
2012-06-28 20:47:37.285 BE_CoreData[3559:1103] backgroundMOC = <NSManagedObjectContext: 0x1f03f050>
2012-06-28 20:47:39.124 BE_CoreData[3559:1103] call contextDidSave
2012-06-28 20:47:40.926 BE_CoreData[3559:1103] call contextDidSave
2012-06-28 20:47:42.071 BE_CoreData[3559:1103] call contextDidSave
2012-06-28 20:47:45.551 BE_CoreData[3559:1103] call contextDidSave
2012-06-28 20:47:45.554 BE_CoreData[3559:1103] Finished refresh operation

Instead of starting with a blank SQLlite store, I seeded a SQLlite store and ran through the same process. The seed loads correctly when it starts up, but the changes since the seed do not appear immediately in the table view. If you scroll to the spot where a row should be added before it’s loaded (and it’s not there), even after the import finishes it does not appear. However, scroll away and come back and the added row appears. It seems that when the database is empty it has nothing to scroll to and therefore doesn’t add anything. With the seed it eventually adds them in but not in the way I’ve seen the core data stores work with an animated insert.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-06T09:32:07+00:00Added an answer on June 6, 2026 at 9:32 am

    As long as your context on the main thread is the same for app delegate and the view controller, it is just a design decision where you perform the merge.

    The merge itself is pretty straightforward.

    1. Register for NSManagedObjectContextDidSave notification.
    2. Launch the background op.
    3. Save on the background thread.
    4. Merge the context in the observer method on main thread.

    Here is the sample code how you perform the merge:

    // Whatever method you registered as an observer to NSManagedObjectContextDidSave
    - (void)contextDidSave:(NSNotification *)notification
    {    
           [self.managedObjectContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) withObject:notification waitUntilDone:YES];
    }
    

    And note, you actually have to save on the background thread for the notification to fire.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm trying to use Apple Core Data Sample code as a basis for my
I'm trying to convert an existing app to use core data. I've set up
I am trying to delete an entity in core data. I use the following
I am working on a simple Core Data app. I have two classes: Client
So I am trying to get a custom object from core data by setting
I created an app from a Xcode template and selected Core Data as an
I am using this Xcode template for core data. On the delegate, I have
hello i'm trying to use core data to read and write user data. the
When trying to use a system supplied NSValueTransformer in Core Data I get the
I'm trying to make Core Data objects inherit from my own custom class rather

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.