B.S.
B.S.

Reputation: 21726

How to make MainThread wait till some async action is done?

I have UITableView with some content, which is loaded in asynchronous way. When user rotates the device I need to make [tableView reloadData] in -willRotateToInterfaceOrientation method. ReloadData works asynchronous in my case.

I understand that reloadData works in main thread, but it fires cellForRowAtIndexPath, which works async in my case.

So the question is how to make main thread wait till UITableView's reloadData ends.

Upvotes: 5

Views: 3269

Answers (3)

NSProgrammer
NSProgrammer

Reputation: 2396

If you call reloadData from willRotateToInterfaceOrientation then it is called on the main thread. In fact UIViews are NOT thread safe and should only ever be dealt with from the main thread (in case for some reason someone gets the idea to call reloadData from another thread).

I think there is confusion relating to "asynchronous" as a term. Asynchronous callbacks for UI delegates like willRotateToInterfaceOrientation are called on the main thread. To be asynchronous does not necessarily mean a different thread (though running asynchronously "in parallel" does).

I would recommend reading up on the Apple documentation for NSRunLoop. It is an integral part of the way iOS apps run and is a must for app programmers to understand.

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html

Upvotes: 2

100grams
100grams

Reputation: 3510

You'll need to load your table's data in the background, then call UITableView's reloadData method.

You can use GCD to easily dispatch your load function asynchronously to a background queue. When that task is finished, have the worker thread dispatch back to the main thread a block that calls [tableView reloadData]. Here's how:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{

  ...
  dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  dispatch_async(queue, ^{

     // load your table data here
     [self loadMyTableData];

     // when done dispatch back to the main queue to load the table
     dispatch_queue_t mainQueue = dispatch_get_main_queue();
     dispatch_async(mainQueue, ^{

        [self.tableView reloadData];
      });
  });
  ...
}

Upvotes: 2

Mehdzor
Mehdzor

Reputation: 799

You may use CFRunLoopRun to make your main thread wait until UITableView data is reloaded. After data is reloaded call CFRunLoopStop passing result of CFRunLoopGetMain as parameter.

Upvotes: 3

Related Questions