关闭所有打开的视图控制器的单个函数
Posted
技术标签:
【中文标题】关闭所有打开的视图控制器的单个函数【英文标题】:single function to dismiss all open view controllers 【发布时间】:2016-02-04 21:23:13 【问题描述】:我有一个应用程序,它是单视图应用程序。我有一个导航控制器链接到根视图控制器中的所有子控制器。
在每个子控制器中,我都有一个注销按钮。我想知道我是否可以有一个可以调用的函数来关闭所有沿途打开的控制器,无论用户按下注销时哪个控制器当前处于打开状态?
我的基本开始:
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
)
这是实现我所追求的最佳方式吗?
【问题讨论】:
您可能只想重新初始化应用的UIWindow
的rootViewController
属性。这将删除您的整个视图层次结构(假设您没有使用其他窗口,这很少见)。
您是在展示控制器还是只是推入导航堆栈?注销按钮在哪里?你可以直接弹出root吗?您还需要做哪些其他清理工作?
@Wain 在某些情况下,我的控制器与 segue 标识符相关联,并且我正在向 ViewControllers 提供已定义的标识符。然后在某些情况下,我只是在做基本的 segues,即按钮的操作、表格行的单击事件。注销按钮作为左栏按钮项添加到导航栏。真的没有其他清理。只需重置一些全局首选项
@Aaron Brager 很抱歉,如果这是一个愚蠢的问题,但您对使用其他窗口到底是什么意思?
@user2363025 ios 应用很少会有多个 UIWindows。您会知道您是否正在制作和管理它们。
【参考方案1】:
您可以拨打:
self.view.window!.rootViewController?.dismiss(animated: false, completion: nil)
应该关闭根视图控制器上方的所有视图控制器。
【讨论】:
试一试,让我知道它是怎么回事:),还假设 self 是您从中调用注销的视图控制器。如果它是从其他地方调用的,您需要传递控制器并将 self 替换为您将从中调用注销的控制器。 @Zorayr 只需将false
更改为 true
以进行dismissAnimation,它应该可以工作:self.view.window!.rootViewController?.dismissViewControllerAnimated(true, completion: nil)
@Liam self.view.window!.rootViewController?.dismissViewControllerAnimated(false, completion: nil) let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil) let initialViewControlleripad : UIViewController = mainStoryboardIpad.instantiateViewControllerWithIdentifier("LogIn") as UIViewController self.appDelegate.window = UIWindow(frame: UIScreen.mainScreen().bounds) self.appDelegate.window?.rootViewController = initialViewControlleripad self.appDelegate.window?.makeKeyAndVisible()
这是我的代码
假设我的应用程序测试了 5 次,其中 3 次 'deinit ' 方法有时不会被调用。这有什么问题?后台我的“NSTimer”逻辑正在运行
Swift 3.0 语法是self.view.window!.rootViewController?.dismiss(animated: false, completion: nil)
【参考方案2】:
Swift 4 和 swift 5
的更新答案UIApplication.shared.keyWindow?.rootViewController?.dismiss(animated: true, completion: nil)
当你使用导航控制器时
self.navigationController?.popToRootViewController(animated: true)
【讨论】:
【参考方案3】:适用于 Swift 4 和 Swift 5
为了消除任何不需要的残留 Modal ViewControllers,我使用了它并且工作得很好,没有保留任何导航堆栈引用。
UIApplication.shared.keyWindow?.rootViewController?.dismiss(animated: false, completion: nil)
self.view.window!
在我的情况下确实崩溃了,可能是因为它是模态屏幕并且丢失了对窗口的引用。
【讨论】:
在完成块中的什么位置?【参考方案4】:Swift3
navigationController?.popToRootViewControllerAnimated(true)
【讨论】:
这将关闭所有推送的视图控制器,很好的答案 这是一个很好的答案,不需要进一步解释。【参考方案5】:看看 unwind segues 是如何工作的。它超级简单,即使它包含复杂的导航(嵌套的推送和/或呈现的视图控制器),也可以让您关闭/弹出到层次结构中的某个视图控制器,而无需太多代码。
这是一个非常好的答案(来自smilebot),它展示了如何使用展开转场来解决您的问题 https://***.com/a/27463286/503527
【讨论】:
【参考方案6】:关闭所有模态视图。
斯威夫特 5
view.window?.rootViewController?.dismiss(animated: true, completion: nil)
【讨论】:
有点无耻地将接受的答案复制粘贴为新答案【参考方案7】:如果您有自定义的 UITabbarController,请尝试通过以下方式关闭 UITabbarController 中的顶部 viewController:
class MainTabBarController: UITabBarController
func aFuncLikeLogout()
self.presentedViewController?.dismiss(animated: false, completion: nil)
//......
【讨论】:
【参考方案8】:适用于 Swift 3.0 +
self.view.window!.rootViewController?.dismiss(animated: true, completion: nil)
【讨论】:
【参考方案9】:斯威夫特 使用它直接跳转到您的 ROOT 导航控制器。
self.navigationController?.popToRootViewController(animated: true)
【讨论】:
popToRoot... 不会关闭呈现的控制器,因为它们没有添加到导航堆栈中。以上是关于关闭所有打开的视图控制器的单个函数的主要内容,如果未能解决你的问题,请参考以下文章