NSFetchedResultsController does not display changes from the background thread

My application uses the NSFetchedResultsController associated with the Core Data repository, and it still worked fine, but now I'm trying to make an asynchronous update code, and I'm having problems. I subclassed the NSOperation class to perform my updates and successfully add this new object to NSOperationQueue. The update code is executing as I expect, and I checked this through the debug logs and checked the SQLite repository after it started.

The problem is that after completing my background operation, new (or updated) items do not appear in my UITableView. Based on my limited understanding, I believe that I need to notify the main managedObjectContext file that changes have occurred so that they can be merged. My notification is triggered, the nut does not contain new elements in the table view. If I stopped the application and restarted it, the objects will appear in the table view, which will lead me to the fact that they will be successfully inserted into the master data store, but will not be combined into a managed object The object used in the main thread.

I have included a sample of my init, main operations, and notification methods. Am I missing something important or maybe this is not right? Any help would be greatly appreciated.

- (id)initWithDelegate:(AppDelegate *)theDelegate { if (!(self = [super init])) return nil; delegate = theDelegate; return self; } - (void)main { [self setUpdateContext:[self managedObjectContext]]; NSManagedObjectContext *mainMOC = [self newContextToMainStore]; NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center addObserver:self selector:@selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:updateContext]; [self setMainContext:mainMOC]; // Create/update objects with mainContext. NSError *error = nil; if (![[self mainContext] save:&error]) { DLog(@"Error saving event to CoreData store"); } DLog(@"Core Data context saved"); } - (void)contextDidSave:(NSNotification*)notification { DLog(@"Notification fired."); SEL selector = @selector(mergeChangesFromContextDidSaveNotification:); [[delegate managedObjectContext] performSelectorOnMainThread:selector withObject:notification waitUntilDone:YES]; } 

During debugging, I examined the notification object, which is sent to contextDidSave: and it seems to contain all the elements that were added (excerpt below). This continues to make me think that inserts / updates are happening correctly, but somehow the merge does not start.

 NSConcreteNotification 0x6b7b0b0 {name = NSManagingContextDidSaveChangesNotification; object = <NSManagedObjectContext: 0x5e8ab30>; userInfo = { inserted = "{(\n <GCTeam: 0x6b77290> (entity: GCTeam; id: 0xdc5ea10 <x-coredata://F4091BAE-4B47-4F3A-A008-B6A35D7AB196/GCTeam/p1> ; data: {\n changed = 
+4
source share
4 answers

The answer turned out to be unrelated to the published code, which ended, as I expected. For reasons I'm still not entirely sure, this has something to do with the first launch of the application. When I tried to start my update operation at startup after creating the master data store, it worked as expected. I solved the problem by pre-loading the sqlite database version into the application so that when I first started it was not necessary to create empty storages. I would like to understand why this solved the problem, but I planned to do it anyway. I leave it here in the hope that someone else will find it useful and not lose as much time as I did on this.

0
source

The method that receives your notification should really notify your context, you can try something like this, which I do in my application:

  - (void)updateTable:(NSNotification *)saveNotification { if (fetchedResultsController == nil) { NSError *error; if (![[self fetchedResultsController] performFetch:&error]) { //Update to handle the error appropriately. NSLog(@"Unresolved error %@, %@", error, [error userInfo]); exit(-1); // Fail } } else { NSManagedObjectContext *context = [fetchedResultsController managedObjectContext]; // Merging changes causes the fetched results controller to update its results [context mergeChangesFromContextDidSaveNotification:saveNotification]; // Reload your table view data [self.tableView reloadData]; } } 

Hope this helps.

0
source

Depending on the specifics of what you are doing, you may be wrong about this.

In most cases, you can simply assign a delegate using NSFetchedResultsControllerDelegate . You provide an implementation for one of the methods specified in "responseingToChanges" depending on your needs, and then send a tableView message reloadData.

0
source

I had a similar problem in the simulator. I started the upgrade process when moving from the root table to the selected folder. The upgrade process will update CoreData from the web server, save, and then merge, but the data is not displayed. If I looked back and forth several times, it would appear in the end, and once it worked like a clock (but I could never repeat this perfect run). This gave me an idea that perhaps this is the problem of synchronizing threads / events in the simulator, where the table is updating too fast or the notifications are simply not in the queue on the right or something in this direction. I decided to try running in the Tools to find out if I can identify the problem (all CoreData, CPU Monitor, Leaks, Allocations, Thread States, Dispatch and a couple more). Every time I did a β€œfirst run” with a clean list, it has worked fine ever since. Maybe tools slow it down enough?

Ultimately, I need to test the device in order to get an accurate test, and if the problem persists, I will try your solution in the accepted answer (to create a sql-lite db database for download).

0
source

All Articles