简体   繁体   中英

UITableView insertRowsAtIndexPaths causing app to be unresponsive

I have a table view which is populated from a fetched results controller. I'm also using NSTimer to make an API call every minute which pulls in any new data to be displayed. This happens asynchronously using GCD with a new managed object context, and uses mergeChangesFromContextDidSaveNotification to merge the changes in to the main managed object context on completion. This triggers the fetched results controller delegate methods and any new rows are inserted into the table with insertRowsAtIndexPaths.

This is all working as expected, however I'm seeing a 5 second pause between UITableView endUpdates being called and the new cell appearing in the table view. During this pause the app doesn't respond to any touch events (tab bar, scrolling the table view etc).

I'm a bit confused about where to start debugging this issue - the cell configuration all happens before before the endUpdates call, and doesn't seem to be taking a long time.

The code is reasonably complicated, but I can post it up if required.

EDIT :

Here is a log extract showing the times of each call from the context merge to endUpdates being called:

2011-05-22 15:29:47.119 myapp[4136:7c1b] got background save notification
2011-05-22 15:29:47.124 myapp[4136:7c1b] controllerWillChangeContent
2011-05-22 15:29:47.128 myapp[4136:7c1b] NSFetchedResultsChangeInsert
2011-05-22 15:29:47.132 myapp[4136:7c1b] controllerDidChangeContent
2011-05-22 15:29:47.138 myapp[4136:7c1b] numberOfSectionsInTableView called
2011-05-22 15:29:47.140 myapp[4136:7c1b] numberOfSectionsInTableView called
2011-05-22 15:29:47.144 myapp[4136:7c1b] numberOfRowsInSection called
2011-05-22 15:29:47.157 myapp[4136:7c1b] cellForRowAtIndexPath called
2011-05-22 15:29:47.195 myapp[4136:7c1b] cellForRowAtIndexPath returning configured cell
2011-05-22 15:29:47.212 myapp[4136:7c1b] endUpdates called

You've probably solved the problem yourself by now but I came across this question when I had literally the exact same problem today and think it needs answering for posterity.

What is most likely happening is that you have set up your NSManagedObjectContext on the main thread and are then doing your save on a different thread, causing the animations on the UITableView (which is on the main thread) to wait until that GCD thread has been taken care of.

Simple fix: do all your computationally intensive stuff as well as the inserting into the MOC within your GCD thread, but then do the save on the main thread, like so:

dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{       
  // Do all your processing and inserting here

  // ... and then, when you're done:
  dispatch_async( dispatch_get_main_queue(), ^{
      NSError *anyError = nil;
      BOOL success = [self.managedObjectContext save:&anyError];
      if(!success) {
          // Error handling
      }
  });
});

Did you check how much time it takes for tableView:cellForRowAtIndexPath: to complete? Or maybe your "layoutSubviews" in your custom tableview cell takes a lot of time?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM