1

In my app, each cell in the UITableview needs data acquired from an API. To make the app look faster, I am acquiring data for one cell at a time and displaying it by using [tableview reloadData]. But while doing this, the ViewController itself is unresponsive. I cannot hit the back button or the tap a cell(to call didSelectRowAtIndexPath). Is there a solution for this? I am calling the reloadData method like this

 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
        dispatch_async(queue, ^{
            [tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
        });
Sidharth J Dev
  • 927
  • 1
  • 6
  • 25
  • Try `dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [tableView reloadData]; });` – iphonic May 06 '15 at 10:53
  • This almost worked. now i can get the back button to respond. but once it reaches the previous viewcontroller, the app crashes. Can you think of any reason that might happen? – Sidharth J Dev May 06 '15 at 11:07
  • I would like to see the crash log for that, it might be caused by something else, than what you are thinking. – iphonic May 06 '15 at 11:09
  • This is the message(Nothing appears in the crash log, i just get this message near the dispatch call) Thread1:EXC_BAD_ACCESS(code=EXCI386_GPFLT) – Sidharth J Dev May 06 '15 at 11:16
  • Its a Memory Leak, nothing to do with reload though. You must be having something in your class, which is causing the leak, try enable Zombie and check for the crash http://stackoverflow.com/questions/5386160/how-to-enable-nszombie-in-xcode – iphonic May 06 '15 at 11:26
  • found this..can you tell me what to do?`[SecondViewController numberOfSectionsInTableView:]: message sent to deallocated instance 0x7fadfca847f0` – Sidharth J Dev May 06 '15 at 11:32
  • @SidharthJDev You can resolve this issue by following right approach to data load. In this case you can download first you data asynchronously and store this data into an array. Every time when data loaded you can redraw your table using reloadData from the array. – Vijay Masiwal May 06 '15 at 11:34
  • @SidharthJDev It seems to me, after you are going back, your tableview is still trying to reload, and since you have poped out, the tableview has been deallocated. Try to stop your api call or, the method to call if you go back, should fix crash. – iphonic May 06 '15 at 11:37
  • From what I have read, it seems that one simply cannot stop a dispatchQueue. how do I change this dispatch queue into an operationsQueue, so that i can call a `[operationsqueue cancelAllOperations]`? – Sidharth J Dev May 06 '15 at 12:03

4 Answers4

4

Reload the tableView on main thread:

dispatch_async(queue, ^{

// Perform background task. Call webservice etc

                dispatch_async(dispatch_get_main_queue(), ^
            {
                // Perform UI related tasks
                [tableView reloadData];
            }

        });
Aneeq Anwar
  • 1,282
  • 7
  • 20
0

You are currently performing a block in the back, calling to perform a method in the main thread... This is redundant, and you should simply call [tableView reloadData]. If calling reloadData takes so much time that it freezes your UI (The reloading of the table has to happen on the main, UI thread and can't be performed in the back) then you might be doing something wrong.

If there are any network calls done synchronously in any of the table view delegate or data source methods then you should perform them in the back, in an asynchronous way, then only reload the table when the requests are done.

Aviel Gross
  • 9,770
  • 3
  • 52
  • 62
0

It' because you are simply blocking the main thread.
You say that you add one cell time I suppose that the cell contents is returned from one web service. That is not the most appropriate way to deal with a problem like that, also because you are probably opening a lot of connections to download data you require to populate the table view.
-reloadData should be used only when you need to update all the contents of the table view, if you want to add cells at time, you should use -insertRowsAtIndexPaths:withAnimation: wrapped inside -beginUpdates and -endUpdates.

Andrea
  • 26,120
  • 10
  • 85
  • 131
0
int requiredNumberOfCells = 10;
int currentNumberOfCells  = 0;
[tableView reloadData];
dispatch_queue_t tableviewcell = dispatch_queue_create("tableviewcell", NULL);
dispatch_async(tableviewcell, ^{

for (int i = 1;i<=requiredNumberOfCells;i++){
//Fetch details for each cell here
currentNumberOfCells  = i;
    dispatch_async(dispatch_get_main_queue(), ^{
      [tableView reloadData];
    });
 }
});
Britto Thomas
  • 2,092
  • 1
  • 15
  • 28