Ios – Perform fetch without freezing the UI

core-dataiosiphonensfetchedresultscontrolleruser interface

I'm making a small chat app. In my app I'm using NSFetchedResultsController. There are 2 tableViews, 1 for lobby and 1 for the chat room. The problem is that whenever I enter a chat room I have to wait for NSFetchedResultsController to perform fetch and load all the data before I can start typing anything. I was wondering if it's possible to preform fetch in background or somehow let the user start typing before the last messages are loaded.

So if I set that part in viewDidLoad method, my UI just freezes until all the data is loaded:

NSError *_error;
if (![self.fetchedResultsController performFetch:&_error]) {
    NSLog(@"Unresolved error %@, %@", _error, [_error userInfo]);
}

and if I set that piece of code into a separate method and then call that method in viewDidLoad in background

[self performSelectorInBackground:@selector(fetchIt) withObject:nil];

tableView is just not updating, so I have to go back to the first tableView and then come back to get any results.

Thank you.

Any help would be appreciated

update

I did try a few other ways to do it.

Way 1:

-(void)reloadTheTable
{
  [self.tableView reloadData];
}

-(void)fetchIt
{
  NSError *_error;
  if (![self.fetchedResultsController performFetch:&_error]) {
    NSLog(@"Unresolved error %@, %@", _error, [_error userInfo]);
  }
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
  [self performSelectorOnMainThread:@selector(reloadTheTable) withObject:nil waitUntilDone:NO];
  [pool release];
}

- (void)viewDidLoad {
  //some code
  [self performSelectorInBackground:@selector(fetchIt) withObject:nil];
  //some other code
}

result: tableView doesn't show any data, need to re-open that view controller

Way 2:

- (void)viewDidLoad {
  //some code
  dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    NSError *_error;
    if (![self.fetchedResultsController performFetch:&_error]) {
        NSLog(@"Unresolved error %@, %@", _error, [_error userInfo]);
    }
  });
  //some other code
}

result: tableView updates, but UI freezes

Way 3:

-(void)fetchIt
{
  NSError *_error;
  if (![self.fetchedResultsController performFetch:&_error]) {
    NSLog(@"Unresolved error %@, %@", _error, [_error userInfo]);
  }
}

- (void)viewDidLoad {
  //some code
  [self performSelectorOnMainThread:@selector(fetchIt) withObject:nil waitUntilDone:NO];
  //some other code
}

result: UI freezes, table view updates.

As I read somewhere, everything that has to do something with UI must be done on a main thread. But I still can't figure out how to do it without freezing the tableView.

Thank you for reading.

Any help is appreciated

Best Answer

I'm not sure whether this'll work or not, but you can have a try:

- (void)methodThatloadYourData {
  NSError *_error;
  if (![self.fetchedResultsController performFetch:&_error]) {
    NSLog(@"Unresolved error %@, %@", _error, [_error userInfo]);
  }
}

- (void)viewDidLoad {
  //some code

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
                 ^{
                   [self performSelector:@selector(methodThatloadYourData)];
                   dispatch_async(dispatch_get_main_queue(),
                                    ^{
                                      [self.tableView reloadData];
                                    });
                 });

  //some other code
}