NSFetchedResultsController sequential delay in updating a UITableView cell; paste work instantly

I have a UITableView (with custom cells, if that matters) connected to an NSFetchedResultsController . My app also uses push notifications. When a remote notification arrives, I update my (main) data model in two steps:

1) Get the header (with some user data) and save it as the new basic Entity information. Here I call NSManagedObjectContext save() . NSFetchedResultsController takes an insert and runs the didChangeObject delegation method using NSFetchedResultsChangeType = NSFetchedResultsChangeInsert . Table update is instantly updated. (New line added)

2) Download more content related to the cell, through NSURLSession paste it in the above Entity and call the save() method again. NSFetchedResultsController picks up the update again and starts the didChangeObject delegation method using NSFetchedResultsChangeType = NSFetchedResultsChangeUpdate . Here I call my configureCell method. TableView is updated, but with a sequential delay of about 10 seconds.

At both stages (save-context-update-update-targeting), the data to be displayed is already saved by the master data. (For example, inside my configureCell.. method, I know that I am not setting the cell shortcut to nil or the like.

My NSFetchedResultsController delegate methods:

 - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { [self.mainTableView beginUpdates]; } - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { [self.mainTableView endUpdates]; } - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { UITableView *tableView = self.mainTableView; switch(type) { case NSFetchedResultsChangeInsert: [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeUpdate: [self configureCell:(MessageTableViewCell *)[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; } } 

Other things I tried inside case NSFetchedResultsChangeUpdate:

  • Tried calling processPendingChanges before save context
  • reloadRowsAtIndexPaths instead of calling configureCell directly
  • Tried to wrap update methods .. inside beginUpdates and endUpdates (although I already have one pair that should do the job)
  • [tableView reloadData]
  • numberOfRowsInSection not 0!
  • NSFetchedResultsController delegate NSFetchedResultsController run only in the main thread.

In short, all (?) Correct delegate methods are called correctly. However, I see a constant delay of ~ 10 seconds when updating a cell. However, the insertion occurs almost instantly. Any ideas?

+8
ios objective-c uitableview core-data nsfetchedresultscontroller
source share
1 answer

@ Paulw11 comment on dispatch_async... set me in the right direction. The problem is that I used the same ManagedObjectContext in two different threads, although they do not access it at the same time. As soon as I sent my save calls (which were on the background thread) to the main queue (by wrapping it inside dispatch_async(dispatch_get_main_queue,^{ UIUpdate code here }); ), the delays disappeared. A possible explanation is that calling save in the background thread causes the delegate methods in the background thread to be called.

In any case, back to the solution - never use the same ManagedObjectContext between multiple threads. Use parent / child context relationships if you are updating the kernel date in more than one thread. NSFetchedResultsController also blends well with this pattern.

+4
source share

All Articles