一旦下一个视图控制器以模态呈现,立即解雇或删除先前已呈现的模态视图控制器。

7
我的目标是在很多视图中根据每个用户操作以模态方式呈现不同的视图。以下是我想要做的,以获得更清晰的视图层次结构和更好的用户体验。
1. 根视图控制器以模态方式呈现第一个视图控制器。 2. 当我在第一个视图控制器上点击按钮时,第二个视图控制器会模态出现在其上。 3. 一旦第二个视图控制器出现,我希望将第一个视图控制器从视图层次结构中取消或删除。
我可以这样做吗?如果可以,应该如何实现?
如果不能,正确的解决方法是什么?因为我将在每个视图上呈现许多以模态方式呈现的视图控制器。即使我想要关闭当前视图,前一个视图仍然会在当前视图关闭时保留出现。
更新:
VC1(根)> VC2(以模态方式呈现)> VC3(以模态方式呈现在VC2上)。
当我关闭VC3时,VC2仍然在视图内存中。因此,我不希望在关闭VC3后立即出现VC2,而是希望通过从视图层次结构中移除或关闭VC2来查看VC1

enter image description here

需求在这张图片中,当我取消蓝色时,我不想在我的视觉记忆中看到粉色,并希望一旦蓝色出现,立即将其删除。

这就是我想要做的事情。

有什么帮助吗?谢谢。


所以,如果我没有弄错的话,你想要做的是这样呈现:vc1->vc2->vc3,当关闭vc3时,你想要回到vc1,对吗? - Ahmad F
@AhmadF ,我尝试了这样的方式:https://puu.sh/t1jji/a760109c29.png。它能够工作,但如果你将动画设置为true,它不是正确的方式。而且你会发现vc2仍然在内存中。 - Thiha Aung
好的,为了确保我能给您一个有用的答案,最后一个问题:您认为您想要完全以编程方式呈现ViewControllers还是使用segues呈现? - Ahmad F
@AhmadF,任何东西都可以。但是,在我的代码中我使用了segue。 - Thiha Aung
是的,我的用户界面不让我看到粉色的那个。这就是为什么... - Thiha Aung
显示剩余4条评论
3个回答

13

因此,让我们假设您有一个类似于以下的故事板:

enter image description here

应该发生的是:

  • 从第一个视图控制器中展示第二个视图控制器。
  • 从第二个视图控制器中展示第三个视图控制器。
  • 从第三个视图控制器中解除,并返回第一个视图控制器。

在第三个视图控制器中的按钮操作中:

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

通过访问当前视图控制器的 presentingViewController,您可以关闭视图控制器的先前层次结构:

呈现此视图控制器的视图控制器。

通过实现 presentingViewController?. presentingViewController? 意味着:被呈现的当前视图控制器的被呈现者 :)

它可能看起来有点混乱,但它其实很简单。

因此,输出应该类似于(我添加了背景颜色到视图控制器 - 如vc1:橙色,vc2:黑色和vc3:浅橙色 - 以使其更清晰):

enter image description here

编辑:

如果您要删除中间的 ViewController(在本例中为第二个 ViewController),dismiss(animated:completion:)会自动执行此操作:

如果您连续显示多个视图控制器,从而构建了一个呈现的视图控制器堆栈,则在堆栈较低的视图控制器上调用此方法会关闭其直接子视图控制器和该子视图控制器上面的所有视图控制器。当发生这种情况时,只有最顶层的视图以动画方式被取消;任何中间视图控制器都将从堆栈中简单地移除。最顶层的视图将使用其模态转换样式进行解除,该样式可能与堆栈中较低的其他视图控制器使用的样式不同。

关于您所询问的内容:

我认为即使我想关闭当前视图,前一个视图仍然会保留在关闭当前视图后出现。

我认为这在UI上很明显(我觉得这没问题),但正如dismiss文档讨论中提到的那样,第三个和第二个都将从堆栈中删除。 这是正确的方式。


1
我认为它与 self.view.window?.rootViewController?.dismiss(animated: true, completion: nil) 相同。 - Thiha Aung
那么,它是否给出了预期的结果?这就是你想要实现的吗? - Ahmad F
很抱歉,那并不是。我完全想要从视图内存中删除vc2,并且当vc3出现时它将成为vc1> vc3。 - Thiha Aung
没问题,你的意思是在dismiss当前视图控制器后,直接跳转到vc3,对吗? - Ahmad F
对我来说真是非常有用的信息...我想除此之外别无选择了...谢谢。 - Thiha Aung

3
这是我从不同角度的意见:
  1. 根视图控制器呈现第二个视图控制器
  2. 将FirstView添加到Second View上
  3. 当按钮按下时,关闭FirstView Controller。

enter image description here

第二个视图控制器:

class ViewController: UIViewController, FirstViewControllerProtocol {

    weak var firstViewController: FirstViewController?

    override func viewDidLoad() {
        super.viewDidLoad()

        print("Not initiated: \(firstViewController)")

        firstViewController  = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "FirstViewController") as? FirstViewController
        addChildViewController(firstVC!)
        firstViewController?.delegate = self
        view.addSubview((firstViewController?.view)!)

        print("Initiated: \(firstViewController)")
    }

    func dismiss() {
        firstViewController?.view.removeFromSuperview()
        firstViewController?.removeFromParentViewController()

    }
}

FirstViewController,

protocol FirstViewControllerProtocol {
    // Use protocol/delegate to communicate within two view controllers
    func dismiss() 
}

class FirstViewController: UIViewController {

    var delegate: FirstViewControllerProtocol?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func dismiss(_ sender: Any) {
        delegate?.dismiss()
    }

    deinit {
        print("BYE")
    }

}

我会尝试一下。谢谢。 - Thiha Aung
另外,我添加了一些日志信息。当关闭 FirstViewController 时,deinit 方法将被调用并释放内存。 - Willjay
我真的不明白那是什么意思...我认为 @IBAction func dismiss 应该包括第二个视图控制器?如果您不介意,能否请您用三个视图控制器(vc1(根)> vc2 > vc3)发布答案?谢谢。 - Thiha Aung
我的意思是当我关闭vc3时,vc2不应该在内存中,而应该返回到vc1。这就是我在问题中的意思。 - Thiha Aung
听起来你的情况是vc1(根)> navigationController(vc2> vc3)?当dismiss vc2或vc3时,它会返回vc1。 - Willjay

2
你想要的是“取消 unwind segue”:

https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/UsingSegues.html#//apple_ref/doc/uid/TP40007457-CH15-SW8

https://developer.apple.com/library/archive/technotes/tn2298/_index.html

它允许您同时解除多个视图控制器,而不必知道堆栈中有多少个。
在VC1中,您将实现一个名为(例如)unwindToRoot的IBAction。然后,在VC3的故事板中,将您的Done按钮连接到Exit对象并选择unwindToRoot操作。
当按下该按钮时,系统将关闭所有需要关闭以使您返回到VC1的视图控制器。
这比调用presentingViewController?.presentingViewController?.dismiss()更好,因为VC3不需要了解其下方的视图控制器层次结构。

我发现这会在从模态呈现的VC中解开时创建奇怪的动画。解开会以相反的方式重做模态动画,这真的很奇怪。 - Phontaine Judd

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