【问题标题】:Dismissing both UINavigation views and Modal views at once programmatically以编程方式同时关闭 UINavigation 视图和 Modal 视图
【发布时间】:2013-07-10 11:58:42
【问题描述】:

我在这个网站上尝试了一些答案,但似乎都与我的问题无关

我有一个 MasterDetail 应用程序,它有两种我正在使用的 segues。当您按下详细视图上的按钮时,它会使用 push segue 并将另一个详细视图推送到该按钮上。在新的 detailview(刚刚被按下的那个)中有一个按钮,它使用模态 segue 调用另一个 UIView(表单)。

我想要做的是当用户选择一行时,一个 UIAlertView 将显示一条消息,同时(不必在同时时间)它会解除 UIViewcontroller(模态)并从被推送的 Viewcontroller 返回。基本上,我需要能够关闭所有视图控制器、一个模式和一个推送(导航),以便视图返回到它们开始时的原始主屏幕。

我的 UIAlertView 工作正常,我可以使用 [self.dismissViewControllerAnimated:YES completion:nil]; 让模态视图控制器关闭,但我不知道如何关闭下一个 Viewcontroller(位于导航控制器中)。使用这个:[self.navigationController popToRootViewControllerAnimated:NO]; 不起作用。

这里是我要调用函数来删除所有视图的地方:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlWithIDAndChallenge];

    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];

    UIAlertView *message = [[UIAlertView alloc] initWithTitle@"Started" message:@"The challenge has begun!" delegate:nil cancelButtonTitle:@"OK!" otherButtonTitles:nil];

    [message show]

    //right here is where I would normally dismiss the modal VC
    //here is where I would like to dismiss all VC

}

【问题讨论】:

  • 您支持哪些 iOS 版本?如果只有 iOS 6 及更高版本,您可以使用 unwind segues,这样做非常优雅。
  • 当我在您的问题中找到我的问题的答案时的那种感觉。非常感谢。

标签: ios objective-c cocoa-touch uinavigationcontroller storyboard


【解决方案1】:

您可以尝试将[self.dismissViewControllerAnimated:YES completion:nil]; 替换为

self dismissViewControllerAnimated:YES completion:^{
    [parentViewController.navigationController popToRootViewControllerAnimated:YES];
}

我相信 parentViewController 会指向呈现的视图控制器,该块会导致父视图控制器的导航控制器弹出到根视图控制器。

【讨论】:

    【解决方案2】:

    在您展示模态视图的课程中

    调用模式的解除,然后在延迟一段时间后执行选择器,然后执行

    这里是示例代码

    //Write this in the class from where you presented a modal View.
    //Call the function from modal class when you want to dismiss and go to root.
    - (void) dismissAndGoToRoot {
          [self dismissViewControllerAnimated:YES completion:nil];
          [self performSelector:@selector(gotoRoot) withObject:nil afterDelay:0.50];
    }
    
    - (void)gotoRoot {
    
        [self.navigationController popToRootViewControllerAnimated:NO];
    }
    

    这里你会调用函数

    //这就是我通常会忽略模态VC的地方 //这里是我想解雇所有VC的地方

    [self.parentViewController dismissAndGoToRoot];
    

    如果这不起作用,则在模态类中获取 ParentViewController 的实例变量,并在呈现模态视图控制器时分配。

    【讨论】:

    • 好吧,我认为这段代码对我来说是正确的。我不知道如何调用它,因为我的 UIAlertView(当被解雇时应该调用你的函数)不是它自己的函数,而是在 didSelectRowAtIndexPath 中。当 UIAlert 被清除时,我将如何调用你的函数来做出反应?我在我的问题中添加了我的didSelectRowAtIndexPath
    【解决方案3】:

    如果需要,在 iOS 6.0(及更高版本)项目中,您可以使用展开转场。例如,您可以:

    1. 在您的顶级视图控制器(您要展开的控制器,而不是您要展开的控制器)中,编写展开segue方法,在这种情况下称为unwindToTopLevel(我个人认为,如果segue 带有一些关于segue 目的地的指示,这很有用,原因将在下面的步骤3 中变得明显):

      - (IBAction)unwindToTopLevel:(UIStoryboardSegue *)segue
      {
          NSLog(@"%s", __FUNCTION__);
      }
      
    2. 在您将启动展开的 Interface Builder 场景中,control ⌘ - 从视图控制器图标拖动到退出图标以创建展开转场:

      通常你会定义从按钮到出口出口的转场(你已经完成了),但如果你想以编程方式调用转场,你可能想在控制器和展开出口之间创建它,比如如上所示。

    3. 您会得到一个小弹出窗口,其中包含您的展开转场的名称(来自呈现的控制器......这就像魔术一样):

    4. 如果您要以编程方式调用该转场,则必须在 IB 窗口左侧的文档大纲中选择该展开转场,完成此操作后,您可以为展开转场指定一个故事板 ID :

      我通常使用展开转场的名称作为情节提要 ID,但您可以使用任何您想要的名称。

    5. 现在,完成此操作后,您的警报视图可以调用 segue:

      - (IBAction)didTouchUpInsideButton:(id)sender
      {
          [[[UIAlertView alloc] initWithTitle:nil message:@"go home" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil] show];
      }
      
      #pragma mark - UIAlertViewDelegate
      
      - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
      {
          if (buttonIndex != [alertView cancelButtonIndex])
          {
              [self performSegueWithIdentifier:@"unwindToTopLevel" sender:self];
          }
      }
      

    【讨论】:

    • 感谢您的图形回答,它有很大帮助!如果您查看对我的问题的评论和编辑,您会发现我没有像您演示的那样使用 UIAlertView 函数。鉴于此,我将如何执行转场?把它贴在我放评论的地方?
    • 好的,我把它贴在我上面评论的地方,没有任何反应。在日志中我看到:-[blahViewController unwindToTopLevel:]。 IBAction 似乎没有连接到任何东西(它旁边的圆圈是空的)。这应该连接到某个地方吗?
    • @CaptJak 鉴于警报视图是异步运行的,我真的不想显示警报,然后在警报仍然显示且用户解除它之前开始解除视图(可能有效,但似乎就像一个奇怪的 UI 流程)。我要么像我的回答那样做(直到用户点击警报中的按钮后才继续),或者你可以让该顶级控制器的viewDidAppear 显示警报,而不是。 (您可以有一些类属性来指示是否显示警报,并将其设置在您正在 segueing 的控制器 from 中的 prepareForSegue 中。
    • @CaptJak 我不知道为什么您插入 performSegueWithIdentifier 不起作用。如果您使用此clickedButtonAtIndex 技术,则必须为UIAlertView 指定delegate(就像我在示例中所做的那样),但如果您不想使用委托,只需输入performSegueWithIdentifier 行在您的didSelectRowAtIndexPath 中,它应该可以工作。如果不是,我不知道该说什么,因为它适用于我(仅限 iOS 6 及更高版本)。
    • 嗯,我认为这是我身边的 PIBKAC。我把 Unwind IBAction 放在了错误的 VC 中。这太棒了!不过,您对 Alertview 的看法是正确的,但使用它时确实看起来不舒服,我想我会改变它!谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-24
    • 2023-03-20
    • 2020-03-24
    • 1970-01-01
    • 2016-04-14
    • 2023-02-25
    相关资源
    最近更新 更多