我希望我的应用程序可以在每次用户需要时转到第一视图控制器。
因此,我想创建一个函数来关闭所有视图控制器,无论它是在导航控制器中推送还是以模式呈现或打开任何方法。
我尝试了各种方法,但我未能肯定地关闭所有视图控制器。 有没有简单的方法?
试试这个:
self.view.window?.rootViewController?.dismiss(animated: true, completion: nil)
它应该关闭根视图控制器上方的所有视图控制器。
如果这不起作用,您可以通过运行这样的 while 循环来手动执行此操作。
func dismissViewControllers() {
guard let vc = self.presentingViewController else { return }
while (vc.presentingViewController != nil) {
vc.dismiss(animated: true, completion: nil)
}
}
它将关闭所有视图控制器,直到它有一个呈现控制器。
编辑:如果要关闭/弹出推送的视图控制器,您可以使用
self.navigationController?.popToRootViewController(animated: true)
希望对您有所帮助。
如果您使用的是导航,则可以使用第一个 或者,如果您正在演示方式,您可以第二个:
用于导航
self.navigationController?.popToRootViewController(animated: true)
用于模式演示
self.view.window!.rootViewController?.dismissViewControllerAnimated(false, completion: nil)
大家好,这里是Swift-4的答案。
要回到根视图控制器,您只需调用一行代码即可完成工作。
self.view.window?.rootViewController?.dismiss(animated: true, completion: nil)
如果您有启动画面,然后是登录屏幕,并且您想转到登录屏幕,您只需在上面的代码中附加presentviewcontroller。
self.view.window?.rootViewController?.presentedViewController!.dismiss(animated: true, completion: nil)
只需让您的rootViewController
在演示时关闭任何ViewController
。
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
appDelegate.window?.rootViewController?.dismiss(animated: true, completion: nil)
(appDelegate.window?.rootViewController as? UINavigationController)?.popToRootViewController(animated: true)
}
返回到初始视图控制器的策略可能会有所不同,具体取决于视图控制器的堆叠情况。
可能有多种情况,根据您的情况,您可以决定哪种方法是最好的。
场景 1
- 导航控制器设置为根视图控制器
- 导航控制器将视图控制器 A 设置为根
- 导航控制器推送视图控制器 B
- 导航控制器推送视图控制器C
这是一个简单的场景,navigationController?.popToRootViewController(animated:true)
将从任何视图控制器工作,并将您返回到视图控制器 A
场景 2
- 导航控制器设置为根视图控制器
- 导航控制器将视图控制器 A 设置为根
- 视图控制器 A 呈现视图控制器 B
- 视图控制器 B 呈现视图控制器 C
这种情况可以通过上面的答案来解决self?.view.window?.rootViewController.dismiss(animated: true)
,并将带您回到视图控制器A
场景 3
- 导航控制器1设置为根视图控制器
- 导航控制器 1 将视图控制器 A 设置为根
- 导航控制器 1 推视图控制器 B
- 视图控制器 B 呈现导航控制器 2
- 导航控制器 2 将视图控制器 D 设置为根
- 导航控制器 2 推视图控制器 E
现在想象一下,您需要从视图控制器 E 一直回到 A
使用上面的 2 个答案这次不会解决您的问题,因为如果导航控制器不在屏幕上,则无法弹出到 root。
您可能会尝试添加计时器和侦听器以关闭视图控制器,然后弹出可以工作的,我认为上面有一个这样的答案,带有dismissPopAllViewViewControllers
函数 - 我注意到这会导致异常行为,并带有此警告Unbalanced calls to begin/end appearance transitions for
我相信你能做的是解决这种情况
- 首先从导航控制器本身展示您的模态视图控制器
- 现在,您可以更好地控制自己想做的事
所以我会先将上面的内容更改为此体系结构:
- 导航控制器 1 设置为根视图控制器(相同)
- 导航控制器 1 将视图控制器 A 设置为根(相同)
- 导航控制器 1 推视图控制器 B(相同) 导航控制器
- 1 呈现导航控制器 2 (更改)
- 导航控制器 2 将视图控制器 D 设置为根(相同)
- 导航控制器 2 推视图控制器 E(相同)
现在从视图控制器 E 中,如果您添加以下内容:
let rootViewController = self?.view.window?.rootViewController as? UINavigationController
rootViewController?.setViewControllers([rootViewController!.viewControllers.first!],
animated: false)
rootViewController?.dismiss(animated: true, completion: nil)
您将在没有任何警告的情况下一路被送回视图控制器A
您可以根据需要进行调整,但这是如何重置复杂视图控制器层次结构的概念。
使用此代码关闭呈现的视图控制器并弹出到导航根视图控制器 swift 4
// MARK:- Dismiss and Pop ViewControllers
func dismissPopAllViewViewControllers() {
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
appDelegate.window?.rootViewController?.dismiss(animated: true, completion: nil)
(appDelegate.window?.rootViewController as? UINavigationController)?.popToRootViewController(animated: true)
}
}
Swift 5.4
:self.navigationController?.popToRootViewController(animated: true)
弹出堆栈上除根视图控制器之外的所有视图控制器并更新显示。
func popToRootViewController(animated: Bool)
但是,如果您想转到特定的控制器,只需使用以下功能。
func popToViewController(UIViewController, animated: Bool)
弹出视图控制器,直到指定的视图控制器位于导航堆栈的顶部。
要实现您想要的,请修改导航堆栈,然后执行 popViewController。
let allControllers = NSMutableArray(array: navigationController!.viewControllers)
let vcCount = allControllers.count
for _ in 0 ..< vcCount - 2 {
allControllers.removeObject(at: 1)
}
// now, allControllers[0] is root VC, allControllers[1] is presently displayed VC. write back to nav stack
navigationController!.setViewControllers(allControllers as [AnyObject] as! [UIViewController], animated: false)
// then pop root VC
navigationController!.popViewController(animated: true)
有关进一步操作导航堆栈的方法,请参阅此处。如果最顶层的 VC 是模态的,请先将其关闭,然后再使用上面的代码。
创建一个 Unwind Segue(你可以在 Apple Inc. 的版权 https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/UsingSegues.html 找到它。
展开 Segue 可让您关闭已 提出。您可以在界面生成器中创建展开 segue 通过链接 按钮或其他合适的对象到当前视图的退出对象 控制器。当用户点击按钮或与 适当的对象,UIKit 在视图控制器层次结构中搜索 能够处理展开序列的对象。然后,它会关闭 当前视图控制器和任何中间视图控制器 揭示展开续集的目标。
创建展开 segue
-
选择在展开序列结束时应显示在屏幕上的视图控制器。
-
在所选视图控制器上定义展开操作方法。
此方法的 Swift 语法如下:
@IBAction func myUnwindAction(unwindSegue: UIStoryboardSegue)
此方法的 Objective-C 语法如下:
- (IBAction)myUnwindAction:(UIStoryboardSegue*)unwindSegue
3. 导航到启动展开操作的视图控制器。
按住 Control 键点按应启动展开 segue 的按钮(或其他对象)。此元素应位于要关闭的视图控制器中。
拖动到视图控制器场景顶部的 Exit 对象。
https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/Art/segue_unwind_linking_2x.png
- 从关系面板中选择展开操作方法。
在尝试在界面生成器中创建相应的展开 segue 之前,必须在其中一个视图控制器中定义展开操作方法。该方法的存在是必需的,并告诉接口生成器有一个有效的展开 segue 目标。
如果有人在寻找问题答案的Objective-C实现,
[self.view.window.rootViewController dismissViewControllerAnimated:true completion:nil];
func dismiss_all(view: UIView){
view.window!.rootViewController?.dismiss(animated: true, completion: nil)
}
也许您正在寻找的是放松 segue。
展开segue 为您提供了一种将导航堆栈"展开"的方法 通过推送、模态、弹出框和其他类型的 segue。你使用 展开 segue 以"返回"导航中的一个或多个步骤 等级制度。
文档链接: https://developer.apple.com/library/archive/technotes/tn2298/_index.html
最好和首选的方法是创建一个放松的 segue。只需按照此文档 https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/UsingSegues.html 进行操作即可。它可以在代码中或通过界面构建器完成。