【问题标题】:Dismiss two UIViewController at once without animation在没有动画的情况下一次关闭两个 UIViewController
【发布时间】:2019-05-01 09:19:13
【问题描述】:

我有一堆 UIViewControllers,比如A -> B -> C。我想从 C 回到控制器 A。我正在使用以下代码:

DispatchQueue.global(qos: .background).sync {
// Background Thread
DispatchQueue.main.async {
    self.presentingViewController?.presentingViewController?.dismiss(animated: false, completion: {
    })}
}

虽然我将动画设置为 false,但它可以在屏幕上看到控制器 B。如何在不显示中间一个 (B) 的情况下关闭两个 UIViewController?

P.S:我不能直接从根控制器中解散,也不能使用UINavigationController

我搜索了社区,但找不到有关动画的任何信息。

Dismiss more than one view controller simultaneously

【问题讨论】:

  • 这可以通过使用基于UINavigationController 的导航而不是从另一个视图控制器呈现视图控制器来轻松实现。这样您就可以使用setViewControllers 方法一次推送/弹出多个视图控制器,但只有一个动画
  • 对不起,我不能使用导航控制器。
  • 你尝试过使用 unwind segue 吗?
  • 我认为您可以在显示控制器 C 时关闭控制器 B。可以为您解决吗?然后当你解除控制器 C 时,你会回到 A。
  • 是的。这对我来说是一个解决方案。 @gkolunia

标签: ios swift uiviewcontroller


【解决方案1】:

试试这个。

self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)

像这样创建了一个示例故事板

黄色视图控制器类型为ViewController,按钮动作如下

@IBAction func Pressed(_ sender: Any) {
    self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)
}

输出

【讨论】:

  • 这看起来可行,但我认为因为我的控制器有很多内容,这需要时间。顺便说一句,在您的示例中也可以看到红色的
【解决方案2】:

我已经创建了在显示 C 控制器之前关闭 B 控制器的示例。你可以试试。

    let bController = ViewController()
    let cController = ViewController()

    aController.present(bController, animated: true) {

        DispatchQueue.main.asyncAfter(wallDeadline: .now()+2, execute: {

            let presentingVC = bController.presentingViewController

            bController.dismiss(animated: false, completion: {

                presentingVC?.present(cController, animated: true, completion: nil)

            })
        })

    }

但在我看来,使用导航控制器的解决方案最适合这种情况。例如,您可以仅将 B 控制器放入导航控制器 -> 将 navController 呈现到 A 控制器上 -> 然后在 navController 中显示 C -> 然后从 C 控制器中关闭整个 navController -> 您将再次看到 A 控制器。也考虑一下解决方案。

另一种解决方案

我检查了另一个解决方案。 这里的扩展应该可以解决您的问题。

extension UIViewController {

    func dissmissViewController(toViewController: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
        self.dismiss(animated: flag, completion: completion)
        self.view.window?.insertSubview(toViewController.view, at: 0)
        dissmissAllPresentedControllers(from: toViewController)
        if toViewController.presentedViewController != self {
            toViewController.presentedViewController?.dismiss(animated: false, completion: nil)
        }
    }

    private func dissmissAllPresentedControllers(from rootController: UIViewController) {
        if let controller = rootController.presentedViewController, controller != self {
            controller.view.isHidden = true
            dissmissAllPresentedControllers(from: controller)
        }
    }

}

用法

let rootController = self.presentingViewController!.presentingViewController! //Pointer to controller which should be shown after you dismiss current controller
self.dissmissViewController(toViewController: rootController, animated: true) 

// 所有以前的控制器也将被解散, // 但你不会看到它们,因为我将它们隐藏并添加到当前视图的窗口中。

但我认为解决方案可能无法涵盖您的所有情况。如果您的控制器未在整个屏幕上显示,则可能会出现问题,所有类似的事情,因为当我模拟该转换时,我不考虑事实,因此您可能需要根据您的特定情况调整扩展。

【讨论】:

  • 对不起,我不想每次打开 C 时都松开 B。有时用户想回到 B
  • @EmreÖnder 在这种情况下,只有带有导航控制器的解决方案才能完全满足您的要求。我在上面的回答中描述了这一点。如果你需要,我也可以举个例子。
  • 谢谢你,但我现在不能在我的项目中使用导航控制器,因为它有很多控制器和代码。这 A、B、C 只是一个例子。
  • 我明白了。我有另一个想法,但它需要检查,当我检查时,我会回复你。
  • 好的。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-18
  • 1970-01-01
  • 2016-09-15
  • 2014-03-08
  • 1970-01-01
相关资源
最近更新 更多