push segue后使用导航堆栈删除视图控制器(使用Storyboard segues)

时间:2015-01-20 18:45:12

标签: ios objective-c uinavigationcontroller uistoryboardsegue

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

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

4 个答案:

答案 0 :(得分:3)

只需替换UIWindow rootViewController 即可。 controllerA controllerB 可以是您想要的任何Viewcontroller - 类。

您可以使用简单的UITableViewController作为登录页,然后用UIWindow替换UINavigationController rootViewController controllerB

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

答案 1 :(得分:3)

我知道这个问题有点老了,但是我自己经历了这个问题后,终于找到了一个解决方案,我觉得这个解决方案比接受的答案要好。

  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. 您唯一需要做的就是将以下行添加到初始viewcontroller的viewDidLoad中:

    navigationItem.hidesBackButton = true
    
  4. 动画设置为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 :(得分:0)

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];

答案 3 :(得分:0)

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

 final class A: UIViewController {

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