Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perform fetch without freezing the UI

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

like image 421
Novarg Avatar asked Jan 11 '12 12:01

Novarg


1 Answers

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
}
like image 70
Kjuly Avatar answered Sep 29 '22 11:09

Kjuly