如何在Swift iOS中关闭两个视图控制器?

13

如何在Swift iOS中关闭两个视图控制器?

以下是我的代码。

@IBAction func backButtonTapped(sender: AnyObject) {
    self.presentingViewController
        .presentingViewController
        .dismissViewControllerAnimated(true, completion: nil)
}

我希望这个链接能够帮助你:https://dev59.com/_2Af5IYBdhLWcg3wbCJ3 - ErasmoOliveira
你的代码已经在iOS 8.1+和Swift 2.2+上正常运行了。问题出在哪里? - Cœur
4个回答

18

Swift 3+版本。您可以使用以下代码在Swift 3中同时关闭两个视图控制器。

func dismissTwoViews() {
    self.presentingViewController?
        .presentingViewController?.dismiss(animated: true, completion: nil)
}

Swift 4+版本。只需使用此扩展即可弹出特定的视图控制器。

extension UINavigationController {

func popToViewController(ofClass: AnyClass, animated: Bool = true) {
    if let vc = viewControllers.filter({$0.isKind(of: ofClass)}).last {
        popToViewController(vc, animated: animated)
    }
}

func popViewControllers(viewsToPop: Int, animated: Bool = true) {
    if viewControllers.count > viewsToPop {
        let vc = viewControllers[viewControllers.count - viewsToPop - 1]
        popToViewController(vc, animated: animated)
    }
}

}

在您的视图控制器类中使用如下方式

for controller in self.navigationController!.viewControllers as 
    Array {
                  if controller.isKind(of: 
    yourPopControllerName.self) {

   self.navigationController?.isNavigationBarHidden = false
                                _ =  
self.navigationController!.popToViewController(controller, 
 animated: false)
                                    break
                                }
                            }

3
这段代码看起来与问题中发布的完全一样。那么有什么区别呢?在Swift2中,它只会关闭一个控制器,而在Swift3中,它会关闭两个控制器? - Mixaz
@Mixaz 我刚在 Swift 2.2 + iOS 8.1 (Xcode 7.3) 上进行了测试,问题中的代码已经可以正常工作。因此,差异可能来自更早版本的 Swift(非常不可能!),或者来自更早版本的 iOS(如 8.0 或 7.x)。 - Cœur

15

有一个特殊的返回segue,它旨在回滚到堆栈中的某个视图控制器。

让我们将最顶层的控制器(从哪里开始)称为,将堆栈中要回滚到顶部的控制器称为目标

  1. 目标中创建IBAction以在返回segue上触发:

    @IBAction func myUnwindAction(segue: UIStoryboardSegue) {}

它可以是空的。

  1. 控制器中,通过从控制器图标拖动到退出一个图标来创建一个返回segue,它会找到您在步骤1中创建的操作。将segue命名为unwind

  2. 现在,您可以使用常规代码发出该segue

    performSegueWithIdentifier("unwind", sender: nil)

我描述了如何从代码中发出返回segue。对于按钮,可以直接在IB中通过将按钮拖动到退出图标来创建返回segue。

还可以查看这个讨论以获取更多信息:如何在编程中执行Unwind segue?


当我这样做时,我收到一个运行时错误,“接收器没有标识符的segue”。 - peacetype
3
这篇教程也许会有所帮助:https://medium.com/@mimicatcodes/create-unwind-segues-in-swift-3-8793f7d23c6f - makle
太棒了,我遇到了“没有与标识符unwind相匹配的段错误”问题,但最终我只是将按钮右拖到顶部的退出处,并删除了之前在按钮中的执行代码,然后完美地解决了。谢谢。 - Tony Merritt
很好的答案。但是如何避免在“取消”操作期间被解除的屏幕闪烁? - Volodymyr Kulyk
这是正确的答案,如果您对任何步骤感到困惑,@Mattk90提供的教程链接易于跟踪。 - iOS_Mouse

2
您一次只能解除一个视图控制器。请尝试以下方法。
@IBAction func backButtonTapped(sender: AnyObject) {
        self.presentingViewController?.dismissViewControllerAnimated(true, completion: {
            let secondPresentingVC = self.presentingViewController?.presentingViewController;
            secondPresentingVC?.dismissViewControllerAnimated(true, completion: {});
        });
}

0

Swift 4:

创建了一个扩展功能,用于UIViewController,可以根据提供的次数弹出NavigationController堆栈中的UIViewControllers。

extension UIViewController {

    func pop(numberOfTimes: Int) {
        guard let navigationController = navigationController else {
            return
        }
        let viewControllers = navigationController.viewControllers
        let index = numberOfTimes + 1
        if viewControllers.count >= index {
            navigationController.popToViewController(viewControllers[viewControllers.count - index], animated: true)
        }
    }
}

我认为 pop(numberOfTimes) 在可读性方面有些误导人。那么 pop(numberOfViewControllers: Int) 怎么样? - Jojo Narte

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接