您可以使用setViewControllers(_:animated:)
重新排列视图控制器堆栈。您无需做任何特殊的操作即可使后退按钮正常工作。导航控制器根据其viewControllers
阵列中的第二项(如果存在第二项)设置后退按钮,并在更新viewControllers
阵列时更新后退按钮。
下面是我该如何做到这一点。首先,我们添加一个方法到UIViewController
,询问它是否是特定的userId
的视图控制器。由于大多数视图控制器都没有(也不可能是)正确的视图控制器,它只是返回false
:
extension UIViewController {
func isViewControllerForUserId(userId: Int) -> Bool {
return false
}
}
然后我们在MessagesViewController
重写此方法来返回true
在适当的时候:
extension MessagesViewController {
override func isViewControllerForUserId(userId: Int) -> Bool {
return self.userId == userId
}
}
现在,为了显示特定用户的视图控制器,我们在导航控制器的堆栈中搜索现有的视图控制器。我们采取的行动取决于我们是否找到它:
func showMessageForUserId(userId: Int) {
if let index = navController.viewControllers.indexOf({ $0.isViewControllerForUserId(userId) }) {
navController.moveToTopOfNavigationStack(viewControllerAtIndex: index)
} else {
pushNewViewControllerForUserId(userId)
}
}
如果我们没有发现它,我们做一个新的视图控制器推:
private func pushNewViewControllerForUserId(userId: Int) {
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
vc.userId = userId
self.navController.pushViewController(vc, animated: true)
}
如果我们没有发现它,我们它用这种方法移动到导航堆栈的顶部:
extension UINavigationController {
func moveToTopOfNavigationStack(viewControllerAtIndex index: Int) {
var stack = viewControllers
if index == stack.count - 1 {
// nothing to do because it's already on top
return
}
let vc = stack.removeAtIndex(index)
if (reorderingIsBuggy) {
setViewControllers(stack, animated: false)
}
stack.append(vc)
setViewControllers(stack, animated: true)
}
private var reorderingIsBuggy: Bool {
// As of iOS 9.3 beta 3, `UINavigationController` drops the prior top-of-stack
// when you use `setViewControllers(_:animated:)` to move a lower item to the
// top with animation. The workaround is to remove the lower item from the stack
// without animation, then add it to the top of the stack with animation. This
// makes it display a push animation instead of a pop animation and avoids
// dropping the prior top-of-stack.
return true
}
}
感谢罗布。我在索引处删除它并将其附加后打印出堆栈。它以正确的顺序打印,所以看起来很好。当我调用'''setViewControllers'''时,一切似乎都很好,并且希望VC显示在顶部。然而,VC在获得''deinit'''之前就消失了。你知道为什么以前的VC消失吗? (我只在2个VC上进行测试) – TIMEX
注意:我改变了这一行:'''navController.setViewControllers(stack,animated:false)'''为animated:false,并且全部似乎都正常工作。任何想法为什么做这个改变解决了这个问题? – TIMEX
哪个视图控制器运行'deinit'? –