rihekopo
rihekopo

Reputation: 3350

Reloading UITableView after method finished in background thread

I have a JSON parser that is responsible for getting the data that I would like to display in a UITableView. Everything seems to be correct, except, that I can't reload the table view when the block in the background obtained the data.

This is how I do it now:

-(void)viewWillAppear:(BOOL)animated {


    self.arr =[[NSMutableArray alloc] init];
    self.api = [API new];
    [self.api requestWithCompletionHandler:^(NSArray<NSDictionary *> * result, NSError * error) {

        for (NSDictionary* x in result) {
            NSLog(@"The whole dict object: %@", [x objectForKey:@"datum"]);
            //NSString *grr = [NSString stringWithString:[x objectForKey:@"datum"]];
            [self.arr addObject:x];
        }

        [self reloadTable];

    }];

//    if (self.arr.count > 1) {
//        [self reloadTable];
//    }
//


}

- (void) reloadTable {

      [self.tableView reloadData];

}

I tried to call a function when the task is ready, and also tried to reload the table when the array has content, but unfortunately there is a delay, and I can't do a UI task from the background.

My question is, that what would be the best solution to fix this? Is is possible to notify the reloadTable method somehow outside from the bg thread?

Upvotes: 0

Views: 59

Answers (2)

Jeffery Thomas
Jeffery Thomas

Reputation: 42588

multi-threaded controllers can get complicated. Here is some advice to help you out.

self.api = [API new]; // 1a: Created in the main thread.
[self.api requestWithCompletionHandler:^(NSArray<NSDictionary *> *result, NSError *error) {
    for (NSDictionary* x in result) {
        NSLog(@"The whole dict object: %@", [x objectForKey:@"datum"]);
        [self.arr addObject:x]; // 1b: Updated in the background.
    }

    [self reloadTable]; // 2: Calling a view controller method in the background.
}];

I see two warning flags here.

  1. Objects created on the main thread should not be updated in the background.
  2. Don't call view controller methods in the background.

The easy way out is to dispatch to the main thread right away.

self.api = [API new];
[self.api requestWithCompletionHandler:^(NSArray<NSDictionary *> *result, NSError *error) {
    dispatch_async(dispatch_get_main_queue(), ^{
        for (NSDictionary* x in result) {
            NSLog(@"The whole dict object: %@", [x objectForKey:@"datum"]);
            [self.arr addObject:x];
        }

        [self reloadTable];
    });
}];

There are many other ways of handling main thread/background thread interactions, but I would start with this.

Upvotes: 1

Zaphod
Zaphod

Reputation: 7270

Have you tried to call it on the main thread?

- (void) reloadTable {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.tableView reloadData];
    });
}

Upvotes: 3

Related Questions