【问题标题】:Dismiss view controller when navigating导航时关闭视图控制器
【发布时间】:2020-03-30 05:59:39
【问题描述】:

我正在 swift 中创建一个 IOS 应用程序,但我发现了一个很大的问题。

如果我要在 Android 中执行此操作,我会使用片段并将当前片段替换为新片段,但在 swift 中似乎没有什么与片段相等,所以。

我从视图控制器 A 开始,然后导航到视图控制器 B(用户应该在此视图中选择他们的名字)并且从 BI 想要导航到 C。但是当我导航到 CI 时需要视图控制器 B被解雇以避免堆叠。但是我找不到一个好方法来删除当前的视图控制器并导航到一个新的。

    func navigateToService(selectedCar: String!){

    if let storyboard = storyboard{
        let vc = storyboard.instantiateViewController(withIdentifier: "BookServiceViewController") as! BookServiceViewController

        self.dismiss(animated: true) //<---

        vc.selectedCar = selectedCar

        self.present(vc, animated: true)
    }
}

到目前为止,我已经尝试了很多。但在我的情况下似乎没有任何效果。我在线程中添加的代码只是立即关闭视图,并没有打开新视图。

那么我该如何从 A -> B -> Dimiss B -> C 导航?

临时编辑,将被删除

    func navigateToService(selectedCar: String!){

    self.dismiss(animated: true) {
        if let storyboard = self.storyboard{
           let vc = storyboard.instantiateViewController(withIdentifier: "BookServiceViewController") as! BookServiceViewController


           vc.selectedCar = selectedCar

           self.present(vc, animated: true)
       }
    }

}

【问题讨论】:

  • 如果你想从C回到A,你可以通过storyboard使用unwindSegue,或者popToViewController(viewControllerA)。没有必要解雇B
  • @AlexandrKolesnik 我想解除 B 的原因是因为我使用的是“自动”,当我拖动视图控制器 C(使其解除)时,视图控制器 B 仍然存在。所以我必须在下拉解散时同时解散 C 和 B
  • 你试过self.present(vc, animated: true, completion: { self.dismiss(animated: true) })吗?
  • 在这种情况下,您必须将所选项目从 B 传递给 A,在 completionBlock 中关闭 B,调用 C
  • 您可以尝试将您的第一个 vc 添加为子视图,然后将其从父视图中删除并设置您的下一个视图

标签: ios swift


【解决方案1】:

多次解雇

在这种情况下,您应该解散提供此控制器的控制器以将两者一起解散:

self.presentingViewController!.dismiss(animated: true) // `!` is to makeing sure it's not crashing.

演示:

使用这个简单的代码来演示:

class ViewController: UIViewController {
    @IBAction func present() {
        let destination = storyboard!.instantiateInitialViewController()!
        if presentingViewController != nil {
            // You are not in the A
            if presentingViewController?.presentingViewController != nil {
                // You are in the C
                presentingViewController?.presentingViewController?.dismiss(animated: true)
                return
            } else {
                // You are in the B
                destination.modalPresentationStyle = .currentContext
            }
        }
        present(destination, animated: true, completion: nil)
    }
}

用法:

  1. 创建单视图应用程序
  2. 将按钮拖到视图控制器中
  3. 用提供的代码替换 ViewController
  4. 连接@IBAction
  5. 运行它以查看结果。

完全改变窗口的根:

如果您想摆脱整个堆栈并表现得像从 C 视图控制器开始启动应用程序一样,您只需将窗口的根目录设置为 C .

view.window!.rootViewController = destination

这就像您首先在目标上设置了 initialViewController 箭头。

【讨论】:

    【解决方案2】:

    试试这个代码:-

    首先,您当前呈现的视图(B)使用此代码制作推送视图,然后尝试呈现您的“BookServiceViewController”视图(C)

        let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "Your_Current_Presented_View") as! Your_Current_Presented_View
    
        let nav = UINavigationController(rootViewController: nextVC)
        nav.navigationBar.isHidden = true
        DispatchQueue.main.async {
            self.present(nav, animated: true, completion: nil)
        }
    

    现在之后,调用你的函数

    func navigateToService(selectedCar: String!){
    
    if let storyboard = storyboard{
        let vc = storyboard.instantiateViewController(withIdentifier: "BookServiceViewController") as! BookServiceViewController
    
        self.dismiss(animated: true) //<---
    
        vc.selectedCar = selectedCar
    
        self.present(vc, animated: true)
    }}
    

    【讨论】:

    • B 和 C 都关闭了:/
    • @Pute 我编辑我的答案,因为它不起作用。请尝试我的新代码,我现在正在编辑。提醒一切都变了。
    • 我编辑我的答案,如果不明白请告诉我你的困惑。
    【解决方案3】:

    1.当您导航到 B 时,只需像这样传递 A 控制器对象:- @IBAction func GoToB(_ sender: Any) { 让 Bcontroller = self.storyboard?.instantiateViewController(withIdentifier: "B") as!乙 Bcontroller.Aobje = self self.navigationController?.pushViewController(Bcontroller, 动画: true) }

    2.从 B 导航到 C 的时间使用 A 控制器对象进行导航,如下所示。

    var Aobje = A()
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func BtoC(_ sender: Any) {
        let Ccontroller = self.storyboard?.instantiateViewController(withIdentifier: "C") as! C
             Aobje.navigationController?.pushViewController(Ccontroller, animated: true)
        self.removeFromParent()
    }
    

    【讨论】:

    • 你能说得更具体点吗? :)
    • 我不太明白你的意思
    • 1.在 B 控制器中创建一个 A 控制器类型对象。
    • 我该怎么做? :o
    • 我已经用代码更改了帖子,所以请使用它。
    【解决方案4】:

    在 A 中:

    func goToB(_ sender: Any) {
            guard let controller = self.storyboard?.instantiateViewController(withIdentifier: "B_ViewController") as? B_ViewController else{return}
            self.present(controller, animated: true, completion: nil)
        }
    
    func proceedToC(selectedCar:String){
            guard let controller = self.storyboard?.instantiateViewController(withIdentifier: "C_ViewController") as? C_ViewController else{return}
            controller.car = selectedCar
            self.present(controller, animated: true, completion: nil)
    }
    
    

    在 B 中:

    func goToC(_ sender: Any) {
            if let presenter = self.presentingViewController, presenter.isKind(of: A_ViewController.self), let vc = presenter as? A_ViewController{
                self.dismiss(animated: false) {
                    vc.proceedToC(selectedCar: "Corvette")
                }
            }
    
    

    【讨论】:

    • 这是一种方法。但是,我建议使用@elia 的方式,因为它更优雅
    • 我确实尝试过,但并没有真正奏效。我在应用程序上进行了一些更改,我正在运行这是另一种方式 atm。但我会看看我是否会很快再试一次。 :) 谢谢
    • @Putte 我在演示中尝试了同样的方法,效果很好。
    【解决方案5】:
    self.dismiss(animated: true) {
       # do your job in here
    }
    

    在此处展示您的UIViewController,但您必须获得将展示的UIViewController 的实例。

    编辑

    描述一个协议

    protocol Handler{
        func  handleIt()
    }
    
    
    class AController: UIViewController, Handler {
    
        func handleIt() {
            // present controller C
            /*
             self.present( C Controller )
             */
        }
    ...
    
        func presentFunction(){
    
            var controller = BController()
            controller.delegate = self
    
        }
    
    }
    

    Conformance 使用此协议,然后使用present C controller 设置它。

    class BController: UIViewController{
    
        var delegate: Handler?
    
        func dismissFunction(){
    
            self.dismiss(animated: true, completion: nil)
    
            delegate?.handleIt()
    
        }
        ...
    }
    

    在控制器 B 中,您必须这样描述。因此,当您触发解除函数时,调用 delegate's handleIt 函数。它presentsC来自A

    希望对你有帮助。

    【讨论】:

    • 请检查我的临时编辑。 :) 这就是你的意思?
    • 对,基本可以试试吗?
    • 我试过了。但它关闭了视图控制器 B 和 C :/
    • 实际上工作方案是正确的,因为你是来自 A 的 B,你的基础 UIViewControllerA
    • 是的。我的基础 vc 是 A(也是根),然后我想临时显示 vc B(只是为了选择正确的名称),一旦我按下导航到 C,我想让 vc B 消失。我希望你能理解,我不知道如何解释它足够好。
    猜你喜欢
    • 2013-12-26
    • 1970-01-01
    • 1970-01-01
    • 2018-12-17
    • 2012-03-15
    • 1970-01-01
    • 1970-01-01
    • 2011-09-17
    • 2019-08-04
    相关资源
    最近更新 更多