Refresh UITableView data in background

In my application, I have a UITableViewController.

Its View table is divided into 3 sections.

I download data for each of these sections from my server. For this, I have 3 functions (e.g. f1 f2 and f3). Each updates the corresponding NSArray used as the data source for my table.

Now I want to reload the data using these functions and update the TableView table after performing these 3 functions, but without disturbing the user.

I do not use asynchronous request, blocks, streams, etc., and I am looking for advice.

Actually, here is what I do:

-(void)viewDidLoad { //some settings [NSTimer scheduledTimerWithTimeInterval:15.0 target:self selector:@selector(reloadDatas) userInfo:nil repeats:YES]; dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_async(queue, ^{ [self reloadDatas]; }); } -(void)reloadDatas { dispatch_queue_t concurrentQueue = dispatch_get_main_queue(); dispatch_async(concurrentQueue, ^{ [self f1]; [self f2]; [self f3]; [myDisplayedTable reloadData]; }); } -(void)f1 { //load datas with a url request and update array1 } -(void)f2 { //load datas with a url request and update array2 } -(void)f3 { //load datas with a url request and update array3 } 

But here my tableView is “frozen” until it is updated.

I don't need the execution order of f1 f2 and f3, but I need to wait until these 3 functions are executed before updating my tableView.

Thank you for your help.

EDIT

Thanks for all your answers.

Here is a working solution:

As mros hints, I removed the send queue from viewDidLoad and replaced in reloadDatas:

 dispatch_queue_t concurrentQueue = dispatch_get_main_queue(); 

from

 dispatch_queue_t mainThreadQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

And finally, I reload the table into the main thread

 dispatch_async(dispatch_get_main_queue(), ^{ [myDisplayedTable reloadData]; }); 
+7
source share
4 answers

So, your “background thread” is actually your main thread. You must use dispatch_get_global_queue and specify priority in order to actually get another thread. In addition, sending async to viewDidLoad is useless since all the controller controller life cycle methods are called in the main thread. I would recommend doing something in your f1, f2 and f3 methods:

Start by running an asynchronous request for the URL, then update arrayX in the completion block and reload the specific section of your table view. Thus, all three queries can be executed simultaneously, and the table simply updates the necessary data when each of them ends. Alternatively, if you only want to reload once, just replace the concurrentQueue variable, you have a background thread, and then execute [tableView reloadData] in the main thread.

+4
source

The previous answers are absolutely right. However, your implementation of reloadDatas and viewDidLoad is a bit problematic.

Just clarify:

You want to complete the time-consuming loading of data in the background thread, and then update the interface / cells when your data is ready for the main stream.

Same:

  -(void)viewDidLoad { dispatch_queue_t concurrentQueue = dispatch_queue_create("com.my.backgroundQueue", NULL); dispatch_async(concurrentQueue, ^{ [self reloadDatas]; }); } -(void)reloadDatas { // Expensive operations ie pull data from server and add it to NSArray or NSDictionary [self f1]; [self f2]; [self f3]; // Operation done - now let update our table cells on the main thread dispatch_queue_t mainThreadQueue = dispatch_get_main_queue(); dispatch_async(mainThreadQueue, ^{ [myDisplayedTable reloadData]; // Update table UI }); } 
+3
source

In reloadDatas you should change this line:

 dispatch_queue_t concurrentQueue = dispatch_get_main_queue(); 

To:

dispatch_queue_t concurrentQueue = dispatch_queue_create("some queue", NULL);

But when you call [myDisplayedTable reloadData] , you need to call this operation in the main queue.

 dispatch_async(dispatch_get_main_queue(), ^{ [myDisplayedTable reloadData]; }); 
+2
source

One more thing. Pulling data from the server and updating table cells is quite common. There is no need for queues or timers. Here is an alternative structure.

Say that you are holding mp3 from your server: Your model class: Music.h / m Your model manager: MusicManager.h / m (Singleton) - it will contain an array of musical objects - this singleton is basically your data source; and finally your UItableViewController: MusicTableVC.h / m

In MusicManager.h / m: you have an NSMutableArray that will be loaded with Music.h objects that you pull from the server. You can do this as soon as the application loads, without even waiting for the TableViewController.

Inside MusicManager, you have several helper methods for adding or removing elements from mutableArray and providing the quantity and, of course, your network methods.

Finally: send a notification to your network code. Your UITableViewController should listen / watch this notification and "reload" accordingly.

  [[NSNotificationCenter defaultCenter] postNotificationName:@"NewMusicAdded" object:nil]; 

You request data from your server, analyze the data in the Music objects, add it to your NSMutable array and publish a notification to let you update the table yourself.

Pretty standard recipe.

+1
source

All Articles