如何在继续使用segue之前等待另一个线程完成?

时间:2012-10-21 18:14:20

标签: ios ios5 asynchronous uistoryboardsegue

我有两个UITableViewControllers,我在它们之间使用故事板进行区分。

prepareForSegue:sender:中,第一个VC从Web服务获取NSArray,并使用下载的数据设置目标VC的模型。我将下载部分放入dispatch_queue_t,因此它将异步运行而不会阻止UI线程。我想点击一个表格单元格,让UIActivityIndi​​catorView开始旋转,下载照片,下载照片时,停止微调器并继续使用segue。

在第一个UITableViewController中,我有一个prepareForSegue:sender:方法:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"SelectPlace"]) {
        NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];

        UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc]
                                            initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
        [spinner startAnimating];
        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:spinner];

        __block NSArray *photos = [[NSMutableArray alloc] init];
        dispatch_queue_t downloadQueue = dispatch_queue_create("flickr download", NULL);
        dispatch_async(downloadQueue, ^{
            photos = [FlickrFetcher photosInPlace:[self.places objectAtIndex:indexPath.row] maxResults:50];
        });
        dispatch_release(downloadQueue);
        [spinner stopAnimating];
        [segue.destinationViewController setPhotos:photos withTitle:[[sender textLabel] text]];
    }

}

现在它立即执行segue而不显示微调器或等待下载完成。

如何在不阻塞主线程的情况下异步下载数据以准备目标视图,还能不立即进行隔离?

2 个答案:

答案 0 :(得分:9)

让目标视图控制器加载数据。当用户选择表中的行时,应立即转到新的视图控制器。这是保持用户界面活泼的必要条件。在prepareForSegue中,为目标视图控制器提供加载自身所需的数据。然后在目标视图控制器的viewWillAppear中,异步加载数据。

如果要保持目标视图控制器的通用性并避免从目标视图控制器执行闪烁照片提取,则可以设置具有getThePhotoData方法且具有{{1}的方法的协议在dataSource中设置为self的目标视图控制器中的指针。然后,在目标视图控制器的prepareForSegue中,异步调用viewWillAppear。闪烁照片提取将在[dataSource getThePhotoData]方法中进行,该方法将在触发segue的视图控制器中实现。

答案 1 :(得分:4)

在prepareForSegue中,你无法阻止segue。在拥有所有数据之前,您必须不要触发segue。因此,我建议您创建手动segue,并在下载所有数据时调用它。

例如,事件链可以与此类似:

  1. 在您的VC注册中,在viewDidLoad中通知(dataReady :)并在dealloc中取消注册,
  2. 用户点击下载按钮并触发目标方法,启动微调器动画
  3. 目标方法使用某个块(最好是某些型号)下载所有数据,
  4. 在块结束时发送通知([[NSNotificationCenter defaultCenter] postNotificationName ...),
  5. 你的VC dataReady:被调用,你停止微调并调用[self performSegueWithIdentifier:...]
  6. Segue被触发