在展示新视图控制器后关闭当前视图控制器 - Swift

17

我想要关闭一个视图控制器并呈现一个新的视图控制器,但我不希望旧的视图控制器继续存在。我使用下面的代码来关闭当前的视图控制器和呈现新的视图控制器。但是这种方式在关闭和呈现之间会有一段时间间隔。我不希望用户注意到这一点。因此,我想先呈现新的视图控制器,然后再关闭以前的视图控制器。有没有办法做到这一点?

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let destinationController = self.storyboard?.instantiateViewController(withIdentifier: "login") as! Login
let presentingVC = self.presentingViewController
self.dismiss(animated: false, completion: { () -> Void   in
    presentingVC!.present(destinationController, animated: true, completion: nil)
})

为什么不按顺序调用,先present再dismiss(而不是在present的completion handler中)?所以代码应该是这样的: presentingVC!.present(destinationController, animated: true, completion: nil); self.dismiss(animated: false, completion:nil) - Andreas Oetjen
朋友,为什么你要从堆栈中移除当前视图控制器currentVc? - Mukesh Lokare
你可以通过将动画设置为 false 来直接在需要时取消。 - Mukesh Lokare
@AndreasOetjen 如果我这样做,它会先显示新的VC,然后关闭它,而不是旧的。 - Hos Ap
@Mukesh 因为我不想在用户再次返回时再次显示它。而且如何将动画设置为false可以帮助我? - Hos Ap
@AndreasOetjen 同时执行 present 和 dismiss 将会呈现新视图并关闭同一个。试一下吧。我们必须在 completion handler 中处理它。 - Ram Madhavan
5个回答

12

我认为最好的方法是在你回到目标控制器后解散当前视图控制器。这意味着,使用当前视图控制器来呈现你的destinationController,然后当你回到目标控制器时,将两个视图控制器都解散。


1
我认为这是一个更好的想法,感谢您的帮助。 - Hos Ap

12

免责声明

除非您绝对需要以模态方式呈现新的 VC,否则我建议在两个 VC 之间执行 segue。看起来您只是以模态方式呈现它,因为您想稍后从原始 VC 手动取消它。在我看来,不仅使用 segue 更容易,而且还可以使用我下面概述的方法。

解决方案

这可能不是最优雅的方法,但您可以通过 prepareForSegue 将旧 VC 的实例传递给下一个 VC,然后在新 VC 的 viewDidLoad 中将其关闭。

例如,在您的新 VC 中,您可以添加以下内容:

class NewVC: UIViewController {

    ...
    var prevVC: PrevVC!

    override func viewDidLoad() {
        super.viewDidLoad()

        prevVC.dismiss(animated: false, completion: nil)
    }

}

当你的新视图控制器(newVC)加载时,它会关闭之前的视图控制器。在你的前一个视图控制器(prevVC)类中,你只需要在prepareForSegue中传递实例即可。

class PrevVC: UIViewController {
    ...
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let destinationVC = segue.destination as? NewVC {

            destinationVC.prevVC = self

        }
    }

}

当然,您只需要在需要时展示新VC,其他一切都会被照顾好。


1
看起来他是以模态方式呈现VC的,那么在呈现VC上调用dismiss-call会同时关闭被呈现的VC吗? - JohnnyAW
@JohnnyAW 哦,我明白这里的困境了。之前没有注意到。幸运的是,看起来他只是以模态方式呈现,以便稍后可以手动解除它。因此,如果他只是执行了一个segue,那么就不应该有问题。我会编辑我的帖子,包括这些信息。 - Benjamin Lowry

2
如果你想从VC A展示VC B并在展示时关闭VC A,你可以使用以下代码: 你需要在VC A中编写此代码,以展示你想要展示VC B的按钮。
let parentVC = presentingViewController
dismiss(animated: true) {
    let vc = self.storyboard!.instantiateViewController(withIdentifier...)
    parentVC.present(vc, animated: true)`enter code here`
}

它可能是错误的答案,在特定情况下,因为它返回到“parentVC”的“PresentingViewController”。 - OuttaSpaceTime

0
所以我刚在Xcode13中尝试了这个。VC_A执行一个segue到VC_B。我试图在segue之后解除VC_A的显示,以及将VC_A传递给VC_B并在VC_B的viewDidLoad中解除VC_A的显示。当我解除VC_B的显示时,它回到了VC_A(还打印了deinit,但它从未被调用)。

0

我做的方法是同时使用两种方式

view.dismiss(animated: true, completion: nil)

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

这取决于之前有多少个视图控制器。由于它们都是可选的,因此在您尝试关闭时,Xcode不会抱怨如果您没有它们。如果是这种情况,单个dismiss()函数将正常工作。

我猜这是因为我一开始没有一个好的设计,虽然现在它能够工作,但我认为如果你一开始就有良好的结构,你不会遇到这个问题。


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