如何使主线程等待某个异步操作完成?

5

我有一个带有内容的UITableView,这些内容是以异步方式加载的。当用户旋转设备时,我需要在-willRotateToInterfaceOrientation方法中进行[tableView reloadData]操作。在我的情况下,ReloadData是异步工作的。

我知道reloadData在主线程中工作,但它会触发cellForRowAtIndexPath,在我的情况下也是异步的。

所以问题是如何使主线程等待UITableView的reloadData结束。

3个回答

3

谢谢,我看到这并不容易阅读文档。我会尝试理解。 - B.S.

2
如果您从willRotateToInterfaceOrientation调用reloadData,则它将在主线程上调用。实际上,UIView不是线程安全的,因此只能从主线程处理它们(以防万一有人想从另一个线程调用reloadData)。
我认为“异步”作为术语存在混淆。UI代理的异步回调(例如willRotateToInterfaceOrientation)在主线程上调用。异步并不一定意味着不同的线程(尽管异步“并行”运行时确实如此)。
我建议阅读Apple关于NSRunLoop的文档。它是iOS应用程序运行方式的重要组成部分,对于应用程序员来说必须理解。 https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html

我知道reloadData在主线程中被调用。但是reloadData会调用cellForRowAtIndexPath...而这个方法需要异步加载一些数据。 - B.S.
我明白了,所以你不是在等待reloadData完成,而是等待reloadData触发的异步任务完成。你能修改一下你的问题来反映这一点吗?虽然我不理解为什么你想在异步数据加载时让主线程被占用,但NSRunLoop仍然是你想要的。 - NSProgrammer
需要主线程等待reloadData,因为这样会使旋转动画更加流畅。 - B.S.
对不起,乔治,这个声明并没有告诉我任何可以帮助你的信息。也许你可以通过一个代码示例来说明你要解决的问题,这样我们就能跟上你的思路并提出解决方案。虽然等待主线程可能会起作用,但你只是在陈述你想让我们帮你实现的解决方案,而没有明确问题所在。如果我们能先评估问题,Stack Overflow 的用户通常可以帮助确定解决方案以及实现所需的内容。 - NSProgrammer

2

您需要在后台加载表格数据,然后调用UITableView的reloadData方法。

您可以使用GCD轻松地将加载函数异步分派到后台队列。当该任务完成时,工作线程将返回主线程一个块来调用[tableView reloadData]。以下是方法:

- (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];
      });
  });
  ...
}

为了调用 [self loadMyTableData];,我需要更改一半的代码来存储数据,然后将其推送到我的子类化的uitableviewcells和它的内容。 - B.S.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接