Пропустить / добавить контроллер вида в стек навигации

У меня есть три контроллера вида, встроенные в навигационный контроллер. Я хочу перейти от VC1 к VC3, чтобы в VC3 кнопка "Назад" навигационного элемента направляла пользователя на VC2 вместо VC1. Я думаю, что это должно быть сделано либо добавление VC2 в стек навигации между VC1 и VC3 когда VC3 создается или пропуск второго контроллера вида.

Я попытался это:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if let identifier = segue.identifier {
        switch identifier {
        case "JumpToThirdVCSegue":
            if let secondvc = segue.destinationViewController as? SecondViewController {
                secondvc.performSegueWithIdentifier("ThirdVCSegue", sender: self)
            }
        default: break
        }
    }
}

но я не мог заставить его работать. Возможно выполнение segue невозможно, когда контроллер представления еще не открыт?

каков наилучший способ пропустить контроллер вида / добавить контроллер вида в середине стека навигации? Я надеюсь, это поможет вам понять, что я пытаюсь сделать:

5 ответов


что-то вроде этого должно работать:

    self.navigationController?.pushViewController(viewController2, animated: true)
    self.navigationController?.pushViewController(viewController3, animated: true)

EDIT:

Если вы хотите нажать второй контроллер вида, не будучи замеченным пользователем, вам нужно добавить его в навигационный контроллер после нажатия третьего контроллера вида. Это можно сделать путем реализации UINavigationControllerDelegate. Второй контроллер представления можно сохранить в переменной и вставить в иерархию навигационных контроллеров в методе delegate. Ваш главный контроллер вида будет выглядеть так следующий:

class MyViewController: UIViewController, UINavigationControllerDelegate {

    var viewControllerToInsertBelow : UIViewController?

    override func viewDidLoad() {
        super.viewDidLoad()
        self.navigationController?.delegate = self
    }

    func pushTwoViewControllers() {
        if let viewController2 = self.storyboard?.instantiateViewControllerWithIdentifier("id1"),
            let viewController3 = self.storyboard?.instantiateViewControllerWithIdentifier("id2") { //change this to your identifiers
                self.viewControllerToInsertBelow = viewController2
                self.navigationController?.pushViewController(viewController3, animated: true)
        }
    }

    //MARK: - UINavigationControllerDelegate
    func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
        if let vc = viewControllerToInsertBelow {
            viewControllerToInsertBelow = nil
            let index = navigationController.viewControllers.indexOf(viewController)!
            navigationController.viewControllers.insert(vc, atIndex: index)
        }
    }

}

Edit: используя swift и segues, это должно работать:

override func performSegueWithIdentifier(identifier: String?, sender: AnyObject?) {
    super.performSegueWithIdentifier(identifier, sender: sender);

    if identifier == "JumpToThirdVCSegue" {
        // now the vc3 was already pushed on the navigationStack
        var navStackArray : [AnyObject]! = self.navigationController!.viewControllers
        // insert vc2 at second last position
        navStackArray.insert(viewController2, atIndex: navStackArray.count - 2)
        // update navigationController viewControllers
        self.navigationController!.setViewControllers(navStackArray, animated:false)
    }
}

таким образом, вы переопределяете performSegueWithIdentifier в VC1, чтобы изменить стек навигации, когда сегмент к VC3 фактически был выполнен (и не только в подготовке). Это предполагает, что вы хотите обработать эту специальную логику навигации в VC1.


вы можете использовать метод

func setViewControllers(_ viewControllers: [UIViewController], animated: Bool)

вот документацию (ссылке), что решает UIViewController проблема вприпрыжку. Просто передайте все необходимое UIViewControllers ему (в навигационном порядке) и последний будет сделан как текущий активный UIViewController (если он уже не является активным).


if var navstack = navigationController?.viewControllers{
                    navstack.append(contentsOf: [vc1,vc2])
                    navigationController?.setViewControllers(navstack, animated: true)
                }

работает


моим решением было бы сохранить свойство BOOL, когда вы должны перейти к третьему, а когда не пропустить, например, объявление " shouldSkip’ в VC2, чтобы, если вы установите его в prepare segue, как показано ниже, вы могли действовать в соответствии с этим в VC2

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if let identifier = segue.identifier {
        switch identifier {
        case "JumpToThirdVCSegue":
            secondvc.shouldSkip=true

            }
        default: break
        }
    }
}

а затем в viewDidload VC2 вы должны проверить этот BOOL, и если это правда и выполнить segue, а если не просто двигаться дальше вы также можете пройти проход, когда такой пропуск не нужен