我在导航控制器中嵌入了三个视图控制器。我想从VC1转到VC3,这样在VC3中导航项的后退按钮会将用户引导到VC2而不是VC1。我认为这应该通过在创建VC3时将VC2添加到VC1和VC3之间的导航堆栈或通过跳过第二个View Controller 来完成。
我试过了:
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?
跳过视图控制器/在导航堆栈中间添加视图控制器的最佳方法是什么?我希望这可以帮助你理解我想要做的事情:
答案 0 :(得分:21)
这样的事情应该有效:
self.navigationController?.pushViewController(viewController2, animated: true)
self.navigationController?.pushViewController(viewController3, animated: true)
修改强>
如果要在不被用户注意的情况下推送第二个视图控制器,则需要在按下第三个视图控制器后将其添加到导航控制器。这可以通过实施UINavigationControllerDelegate
来完成。您可以将第二个视图控制器存储在变量中,并将其插入到委托方法中的导航控制器层次结构中。您的主视图控制器将如下所示:
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)
}
}
}
答案 1 :(得分:6)
编辑:使用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)
}
}
所以你覆盖VC1中的performSegueWithIdentifier,以便在实际执行segue到VC3时更改导航堆栈(并且不仅仅是在准备中)。 这假设您要在VC1中处理此特殊导航逻辑。
答案 2 :(得分:3)
if var navstack = navigationController?.viewControllers{
navstack.append(contentsOf: [vc1,vc2])
navigationController?.setViewControllers(navstack, animated: true)
}
效果很好
答案 3 :(得分:2)
您可以使用方法
func setViewControllers(_ viewControllers: [UIViewController],
animated: Bool)
以下是解决UIViewController
跳过问题的文档(link)。
只需将所有需要的UIViewControllers
传递给它(按导航顺序),最后一个将作为当前活动UIViewController
(如果它已经不是活动的那个)。
答案 4 :(得分:1)
我的解决方案是保留一个BOOL属性,当你应该跳到第三个并且不跳过时,比如在VC2中声明'shouldSkip',这样如果你在下面准备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,如果不是继续前进 你也可以在没有必要跳过时传递传球
答案 5 :(得分:1)
基于MarkHim的答案,导航回插入的视图控制器时出现黑屏,所以我想出了以下解决方案。
顺便说一句-我想将新的视图控制器直接插入我刚刚设定的视图控制器下,因此是navStack.count - 1
而不是navStack - 2
。
这是我的解决方案:
override func performSegue(withIdentifier identifier: String, sender: Any?) {
super.performSegue(withIdentifier: identifier, sender: sender)
if identifier == "JumpToThirdViewControllerSegue",
let navController = navigationController { // unwrap optional
// initialize the view controller you want to insert
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewControllerToInsert = storyboard.instantiateViewController(
withIdentifier: "SecondVC") as! SecondViewController
// set any passed properties
viewControllerToInsert.passedProperty = propertyToPass
// create an object using the current navigation stack
var navStackArray: [UIViewController]! = navController.viewControllers
// insert the newly initialized view controller into the navStackArray
navStackArray.insert(viewControllerToInsert, at: navStackArray.count - 1)
// replace the current navigation stack with the one you just
// inserted your view controller in to
navController.setViewControllers(navStackArray, animated: false)
}
}