Question

I am asynchronously loading data to an array in a getter method of data.

First of all it produces an empty array, so naturally my table loads 0 rows.

When the data is finished loading, I call reloadData to update my table, however, there seems to be ~6 second gap between the data being downloaded and the UITableView showing the data.

Does anyone know any reasons this might happen?

I use the dispatch_async method with a priority of high.

I've even logged each point in the process of loading the data and inserting the data, and it shows this.

Also, if I keep scrolling the table up and down as it's data is being loaded, the table shows its data as soon as it should, rather than have this gap between insertion.

Code:

- (NSMutableDictionary *)tableDictionary {
    if (!_tableDictionary) {
        _tableDictionary = [NSMutableDictionary dictionary];

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            NSString *URLString = @"http://www.urlToData.com/path/to/file.php?foo=bar";

            NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:URLString]];
            NSError *error = nil;

            NSDictionary *objectIDs = [NSJSONSerialization JSONObjectWithData:data options:NSJSONWritingPrettyPrinted error:&error];

            NSMutableDictionary *objects = [NSMutableDictionary dictionary];

            for (NSInteger i = 0; i < objectIDs.allValues.count; i++) {
                NSArray *eventIDs = (objectIDs.allValues)[i];
                NSString *eventType = (objectIDs.allKeys)[i];

                [objects setValue:[myObject initWithIDs:objectIDs] forKey:@"key"];
            }

            self.tableDictionary = objects;
            self.titlesForSectionHeader = objects.allKeys;

            NSLog(@"Done");
            [self.tableView reloadData];
        });
    }
    return _tableDictionary;
}
Was it helpful?

Solution

Try reloading your tableview's data on the main thread like this:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        //background processing goes here
        //This is where you download your data
        dispatch_async(dispatch_get_main_queue(), ^{
            //update UI here
            [self.tableView reloadData];
        });
});

OTHER TIPS

As a slight modification of the code by @danielbeard. I would recommend that all code affecting the current object be done on the main queue. This avoids nasty surprises down the road if KVO or a set property updates the UI.

Finally, I wouldn't use DISPATCH_QUEUE_PRIORITY_HIGH.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // Stuff 'n stuff

    dispatch_async(dispatch_get_main_queue(), ^{
        self.tableDictionary = objects;
        self.titlesForSectionHeader = objects.allKeys;

        NSLog(@"Done");
        [self.tableView reloadData];
    });
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top