关闭所有打开的视图控制器的单一功能

single function to dismiss all open view controllers

我有一个单视图应用程序。我有一个导航控制器链接到根视图控制器的所有子控制器。

在每个子控制器中,我都有一个注销按钮。我想知道我是否可以有一个我可以调用的函数,它将关闭一路上打开的所有控制器,无论用户按下注销时当前打开的是哪个控制器?

我的基本起点:

func tryLogout(){
     self.dismissViewControllerAnimated(true, completion: nil)
     let navigationController = UINavigationController(rootViewController: UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("LoginViewController") )
     self.presentViewController(navigationController, animated: true, completion: nil)
}

我正在寻找执行此任务的内存效率最高的方法。我会将我的注销功能放在一个单独的 utils 文件中,但是我不能使用 self.而且我仍然不知道要动态关闭哪个控制器。

更新 已建议弹出到根视图控制器。所以我的尝试是这样的:

func tryLogout(ViewController : UIViewController){
     print("do something")
     dispatch_async(dispatch_get_main_queue(), {
         ViewController.navigationController?.popToRootViewControllerAnimated(true)
         return
     })
 }

这是实现我所追求目标的最佳方式吗?

您可以致电:

self.view.window!.rootViewController?.dismiss(animated: false, completion: nil)

应该关闭根视图控制器之上的所有视图控制器。

看看放松转场是如何工作的。它超级简单,即使它包含复杂的导航(嵌套的推送和/或呈现的视图控制器),也可以让您 dismiss/pop 到层次结构中的某个 viewcontroller,无需太多代码。

这是一个非常好的答案(来自 smilebot),它展示了如何使用 unwind segues 来解决你的问题

斯威夫特3

navigationController?.popToRootViewControllerAnimated(true)

更新了 Swift 4swift 5

的答案
UIApplication.shared.keyWindow?.rootViewController?.dismiss(animated: true, completion: nil)

以及当您使用 navigationController 时

self.navigationController?.popToRootViewController(animated: true)

适用于 Swift 3.0 +

self.view.window!.rootViewController?.dismiss(animated: true, completion: nil)

适用于 Swift 4 和 Swift 5

为了消除任何不需要的残留模态视图控制器,我使用了它并且在不保留任何导航堆栈引用的情况下运行良好。

UIApplication.shared.keyWindow?.rootViewController?.dismiss(animated: false, completion: nil)

self.view.window! 在我的案例中确实崩溃了,可能是因为它是模态屏幕并且丢失了对 window.

的引用

Swift 使用它直接跳转到您的 ROOT 导航控制器。

self.navigationController?.popToRootViewController(animated: true)

如果您有自定义 UITabbarController,请尝试通过以下方式关闭 UITabbarController 中的顶部 viewController:

class MainTabBarController: UITabBarController {

    func aFuncLikeLogout() {

        self.presentedViewController?.dismiss(animated: false, completion: nil)

        //......
    }

}

关闭所有模态视图。

Swift 5


view.window?.rootViewController?.dismiss(animated: true, completion: nil)

我想出了一个通用函数来使用完成块关闭所有呈现的控制器。

extension UIWindow {
    static func keyWindow() -> UIWindow? {
        UIApplication.shared.windows.filter({ [=10=].isKeyWindow }).first
    }
}

func getVisibleViewController(_ rootViewController: UIViewController?) -> UIViewController? {
    
    var rootVC = rootViewController
    if rootVC == nil {
        rootVC = UIWindow.keyWindow()?.rootViewController
    }
    
    var presented = rootVC?.presentedViewController
    if rootVC?.presentedViewController == nil {
        if let isTab = rootVC?.isKind(of: UITabBarController.self), let isNav = rootVC?.isKind(of: UINavigationController.self) {
            if !isTab && !isNav {
                return rootVC
            }
            presented = rootVC
        } else {
            return rootVC
        }
    }
    
    if let presented = presented {
        if presented.isKind(of: UINavigationController.self) {
            if let navigationController = presented as? UINavigationController {
                return navigationController.viewControllers.last!
            }
        }
        
        if presented.isKind(of: UITabBarController.self) {
            if let tabBarController = presented as? UITabBarController {
                if let navigationController = tabBarController.selectedViewController! as? UINavigationController {
                    return navigationController.viewControllers.last!
                } else {
                    return tabBarController.selectedViewController!
                }
            }
        }
        
        return getVisibleViewController(presented)
    }
    return nil
}

func dismissedAllAlert(completion: (() -> Void)? = nil) {

    if let alert = UIViewController.getVisibleViewController(nil) {

    // If you want to dismiss a specific kind of presented controller then
    // comment upper line and uncomment below one

    // if let alert = UIViewController.getVisibleViewController(nil) as? UIAlertController {

        alert.dismiss(animated: true) {
            self.dismissedAllAlert(completion: completion)
        }

    } else {
        completion?()
    }

}

注意:你可以在代码中的任何地方调用任何地方class

使用:-

dismissedAllAlert()    // For dismiss all presented controller

dismissedAllAlert {    // For dismiss all presented controller with completion block
    // your code
}