【问题标题】:Remove view controller from navigation stack after push segue (using Storyboard segues)推送转场后从导航堆栈中删除视图控制器(使用情节提要转场)
【发布时间】:2015-03-19 03:02:27
【问题描述】:

我的应用程序包含在 aUINavigationController 中。根视图控制器 A 本质上是一个登录视图,用户将在其中输入凭据,成功后将通过推送 segue 显示配置文件视图控制器 B。现在,用户在 B 的导航栏上获得了返回按钮以导航回 A。我希望 B 现在成为导航堆栈上的根视图控制器,从而有效地防止用户在新应用启动之前返回到 A

在仍然使用 push segue 的同时处理这个问题的正确方法是什么?我应该在没有 segue 的情况下执行 B 的演示并使用新的导航控制器有效地启动 B 吗?

【问题讨论】:

  • 最好将B设为导航控制器的根视图控制器。从 B 的 viewDidAppear 方法以模态方式(没有动画)呈现 A,它将是用户看到的第一件事。当您解雇它时,它将被释放,您将在 B 处。
  • 我 100% 同意你的观点,但是我必须遵守一些特定的规范,这就是我尝试这种方式的原因。我确实认为您的建议将是解决此问题的一种简单方法,所以也许我会尝试一下,看看它是否比原始规格更受欢迎。

标签: ios objective-c uinavigationcontroller uistoryboardsegue


【解决方案1】:

我知道这个问题有点老了,但是我自己经历了这个,我终于找到了一个我认为比公认的答案更好的解决方案。

  1. 使登录控制器成为导航控制器的根控制器。

  2. 登录成功后,从导航控制器 viewcontrollers 数组中删除登录控制器,并附加您应用的初始 viewcontroller。

    if let navigationController = navigationController {
    
        var viewControllers = navigationController.viewControllers
    
        for (index, viewController) in viewControllers.enumerated() where viewController is LoginViewController {
            viewControllers.remove(at: index)
        }
    
        let storyBoard = UIStoryboard(name: "Main", bundle: Bundle.main)
        let initialViewController = storyBoard.instantiateViewController(withIdentifier: "InitialViewController")
    
        viewControllers.append(initialViewController)
    
        navigationController.setViewControllers(viewControllers, animated: true)
    }
    
  3. 您唯一需要做的就是将以下行添加到初始视图控制器的 viewDidLoad:

    navigationItem.hidesBackButton = true
    

将动画设置为 true 的 setViewControllers 方法负责处理您指定为要求的推送动画。

编辑:

我制作了一个可以添加到登录控制器的方法,它不仅适用于您希望登录控制器显示为应用程序中的第一个视图控制器,而且还适用于以后的身份验证失败(过期凭据等)。 ) 并且您已经以模态方式显示了登录控制器:

    func authenticationDidSucceed() {
        // If the LoginController is in a navigation stack then
        // replace it with the initial viewcontroller of the app
        guard navigationController?.viewControllers.contains(self) ?? false else {
            // Else it must be presented modally, so dismiss it
            dismiss(animated: true, completion: nil)
            return
        }

        guard let navigationController = navigationController else { return }

        var viewControllers = navigationController.viewControllers

        if let index = viewControllers.index(of: self) {
            viewControllers.remove(at: index)
        }

        viewControllers.append(UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "InitialViewController"))

        navigationController.setViewControllers(viewControllers, animated: true)
    }

只要记住上面的第 3 步即可。

【讨论】:

  • 这对我有用,效果很好,谢谢。我对此非常陌生,而这个答案几乎不需要额外的知识。
【解决方案2】:

只需替换您的UIWindowrootViewControllercontrollerAcontrollerB 可以是您想要的任何Viewcontroller-Class。

您可以在 Loginpage 中使用简单的 UITableViewController,然后将 UIWindowrootViewController 替换为 UINavigationController 持有 controllerB强>

[UIView transitionFromView:controllerA.view
                        toView:controllerB.view
                      duration:0.65f
                       options:(UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionCrossDissolve)
                    completion:^(BOOL finished){
                        delegate.window.rootViewController = controllerB;
                    }];

【讨论】:

  • 这是我目前最终采用的解决方案。感谢您的回答!
【解决方案3】:

我使用 segue 从一个 controller A 导航到另一个 controller B,我想在推送到 controller B 后取消初始化 controller A 所以,我想说这是最干净和最简单的方法删除 viewDidDisappear 中的 controller A 并取消初始化。

 final class A: UIViewController {

    override func viewDidDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.viewControllers.removeAll(where: { self === $0 })
    }
}

【讨论】:

    【解决方案4】:

    B 应该包含在它自己的导航控制器中,因为 A 将不再可访问。您将不得不使用 push segue 以外的其他东西。 transitionWithView 效果很好:

    UINavigationController *newNavController;
    
    [UIView transitionWithView:delegate.window
                      duration:0.5
                       options:UIViewAnimationOptionTransitionCrossDissolve
                    animations:^
     {
         [delegate.window addSubview:newNavController.view];
     }
                    completion:^(BOOL finished)
     {
         delegate.window.rootViewController = newNavController;
     }];
    
    [delegate.window makeKeyAndVisible];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-11
      • 2012-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多