如何在收到协议信息后执行 segue

How to perform segue after information from protocol is recieved

我在一个单元格中有一个按钮,它调用一个协议,该协议具有需要由 segue 传递给视图控制器的数据。 segue 是通过故事板发生的。当按下按钮时,我当前的代码使用 shouldperformsegue 到 return no,因为发生的第一个 segue 没有数据。 我猜 segue 和协议正在异步处理。

但在我 return NO 之前,我告诉它延迟执行 segue。这个延迟的 segue 确实有数据并且工作正常。

我的问题是有没有办法等待协议完成然后执行 segue?也许有一个执行块?

UIViewController 上查看 performSegueWithIdentifier。如果您在情节提要中的视图控制器之间设置了一个 segue( 而不是 从按钮)并给它一个标识符,您可以在数据准备好后立即执行 segue。

既然您提到您的数据是异步获取的,您可能需要像这样将 performSegueWithIdentifier 调用分派到主线程:

dispatch_async(dispatch_get_main_queue(), ^{
  [self performSegueWithIdentifier:@"jumpToOtherViewController" sender:self];
});

要实际将数据传递到下一个视图控制器,您可以使用 prepareForSegue 描述 here

是的,我会使用积木。例如:

[Api getDataWithCompletion:^(BOOL success, NSString *data) {
    if (success) {
        self.data = data;
        [self performSegueWithIdentifier:@"MySegue" sender:self];
    } else {
        NSLog(@"Failed to get data");
    }
}];

然后,将其传递给下一个视图控制器:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"MySegue"]) {
        TargetViewController *targetVC = (TargetViewController*)segue.destinationViewController;
        targetVC.data = self.data;
    }
}

其他回复者已经暗示了,但没有明确说明,所以就这样吧。

不要将 segue 直接绑定到按钮。相反,按住控制键从源视图控制器 SCENE 拖动到目标场景,以在视图控制器级别创建一个 segue。给 segue 一个唯一的标识符。

然后,在您的按钮 IBAction 代码中,执行异步网络下载。您可能希望在下载过程中显示 "loading, please wait" 消息或其他内容。大多数异步网络调用都需要一个完成块。在该完成块中,将对 performSegueWithIdentifier 的调用包装在对 dispatch_async(dispatch_get_main_queue() 的调用中,以便在主线程上调用 segue。 (@SantaClaus 的回答显示了它的语法。)

因此您的按钮 IBAction 代码可能如下所示:

- (IBAction) buttonAction: (UIButton *) sender;
{
  //Display a "please wait"message to the user if desired
  doAsyncCallTakingBlock( completion: ^(NSData *data)
  {
    //parse the data, (or whatever)

    dispatch_async(dispatch_get_main_queue(), ^
    {
      //This call uses the button as the sender. That might be appropriate,
      //or not. 
      [self performSegueWithIdentifier:@"jumpToOtherViewController" 
        sender: sender];
    });
  }
}

使用这种方法,直到异步方法(我在我的示例代码中调用 doAsyncCallTakingBlock)完成它的工作,才会调用 segue。您可以调用 Alamofire 请求方法、使用 NSURLSession 或任何其他采用完成块的异步方法。