简体   繁体   English

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

[英]Remove view controller from navigation stack after push segue (using Storyboard segues)

My app is contained in a UINavigationController . 我的应用程序包含在UINavigationController The root view controller A is essentially a login view, where the user will enter credentials and upon success will present the profile view controller B via a push segue. 根视图控制器A本质上是登录视图,其中用户将输入凭证,并且一旦成功将通过推送segue呈现简档视图控制器B. Right now the user gets the back button on the nav bar of B to navigate back to A . 现在,用户获得B导航栏上的后退按钮以导航回A。 I want B to now be the root view controller on the navigation stack, effectively preventing the user from ever getting back to A until a new app launch. 我希望B现在成为导航堆栈上的根视图控制器,有效地防止用户在新的应用程序启动之前回到A。

What is the correct way to handle this while still using a push segue? 在使用push segue的同时处理此问题的正确方法是什么? Should I perform the presentation of B without a segue and effectively start B off with a new navigation controller? 我应该在没有segue的情况下执行B的演示并使用新的导航控制器有效地启动B关闭吗?

Just replace the rootViewController of your UIWindow . 只需替换UIWindowrootViewController即可 controllerA and controllerB can be any Viewcontroller -Class you want. controllerAcontrollerB可以是您想要的任何Viewcontroller类。

You could use a simple UITableViewController for the Loginpage and then replace the rootViewController of your UIWindow with a UINavigationController holding controllerB 您可以使用一个简单的UITableViewController作为Loginpage ,然后使用保存controllerBUINavigationController替换UIWindowrootViewController

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

I know the question is slightly old, but having gone through this myself, I have finally found a solution which I think is better than the accepted answer. 我知道这个问题有点老了,但是自己经历了这个问题后,我终于找到了一个解决方案,我认为这个解决方案比接受的答案要好。

  1. Make the login controller the root controller of the navigation controller. 使登录控制器成为导航控制器的根控制器。

  2. When login succeeds, remove the login controller from the navigation controllers viewcontrollers array and append your app's initial viewcontroller. 登录成功后,从导航控制器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. The only other thing you have to do is add the following line to your initial viewcontroller's viewDidLoad: 您唯一需要做的就是将以下行添加到初始viewcontroller的viewDidLoad中:

     navigationItem.hidesBackButton = true 

The setViewControllers method with animated set to true takes care of the push animation you specified as a requirement. 将动画设置为true的setViewControllers方法负责处理您指定为需求的推送动画。

EDIT: 编辑:

I have made a method that can be added to the login controller, which not only works if you want the login controller to be shown as the first view controller in the app, but also if later authentication fails (expired credentials etc.) and you have shown the login controller modally: 我已经创建了一个可以添加到登录控制器的方法,这不仅适用于您希望登录控制器显示为应用程序中的第一个视图控制器,而且还有以后的身份验证失败(过期的凭据等)和您以模态方式显示登录控制器:

    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)
    }

Just remember step 3 from above. 请记住上面的第3步。

B should be contained in it's own navigation controller since A will no longer be accessible. B应该包含在它自己的导航控制器中,因为A将不再可访问。 You'll have to use something other than a push segue. 你必须使用push segue以外的东西。 transitionWithView works well: 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];

I was using segue to navigate from a controller A with navigation to another controller B , And i wanted to get controller A deinitialized after the pushing to controller B so, I would say this was the cleanest and easiest way to remove controller A in viewDidDisappear and get it deinitialized. 我用SEGUE从导航controller A导航到另一个controller B ,而我希望得到controller A deinitialized后推到controller B的话,我会说这是为了去除干净,最简单的方法controller AviewDidDisappear和把它取消初始化。

 final class A: UIViewController {

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用Storyboard Segues将视图控制器从模态推送到模态父级使用的导航控制器 - Push view controller from modal into navigation controller used by parent of the modal using Storyboard segues 而不是 push segue 如何替换视图控制器(或从导航堆栈中删除)? - Instead of push segue how to replace view controller (or remove from navigation stack)? 如何对不同情节提要中的导航堆栈中的特定视图控制器执行推选? - how to perform push segue to certain view controller in navigation stack in the different storyboard? 故事板中一个视图控制器的多推送段 - Multiple Push Segues to One View Controller in Storyboard 您可以从多个导航控制器中选择一个情节提要视图控制器吗? - Can you segue to a storyboard view controller from multiple navigation controllers? 多个搜索删除视图控制器中的导航栏 - Multiple segues remove navigation bar in view controller 使用情节提要segue的ios导航堆栈 - ios navigation stack using storyboard segue 在Segue期间从UINavigationController的导航堆栈中删除视图控制器? - Removing a view controller from the navigation stack of UINavigationController during segue? 模态导航到视图控制器,然后使用推式搜索进行导航 - Navigating to a view controller modally and then navigation using push segue iOS:从导航堆栈中删除视图控制器 - iOS: remove view controller from navigation stack
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM