我的应用程序有一个TabBarController。每个tabBarItem都与NavigationController中嵌入的ViewController相关。
当在第一个tabBarItem中并选择另一个tabBarItem时,我想在移动到选定的ViewController之前做一些事情。因此,我为tabBarController创建了一个类,并将其命名为UITabBarControllerDelegate。
我想做的是用两个按钮发出警报;按钮A取消移动到选定的视图控制器,按钮B允许移动。
我的问题是,当按下按钮B时,我想弹出RootViewController。我给navigationController一个故事板ID,并尝试如下所示实例化它。
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if let alert = self.storyboard?.instantiateViewController(withIdentifier: "ActiveSessionWarningAlert") as? ActiveSessionWarningAlert {
alert.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
alert.modalTransitionStyle = UIModalTransitionStyle.flipHorizontal
let alertWasDismissed: (Bool) -> Void = { userWantsToMoveToSelectedViewController in
if userWantsToMoveToSelectedViewController {
if let navContr = self.storyboard?.instantiateViewController(withIdentifier: "firstNavContr") as? UINavigationController {
navContr.popToRootViewController(animated: true)
}
tabBarController.selectedViewController = viewController
}
}
alert.alertWasDismissed = alertWasDismissed
self.present(alert, animated: true, completion: nil)
}
return false
}
一切都按预期进行,但popToRootViewController似乎没有出现;当再次选择第一个tabBarItem时,我们离开该项目时处于"活动"状态的同一个viewController仍在显示。
我检查了一下,以便我想弹出的viewController实际上在导航堆栈中,并且navContr!=无
我错过了什么?
您没有这么说,但我假设当用户解除警报时,您传递给警报视图控制器的alertWasDismissed
闭包会被调用。
你的关闭问题在于:
if let navContr = self.storyboard?.instantiateViewController(withIdentifier: "firstNavContr") as? UINavigationController
任何时候调用instantiateViewController(withIdentifier:)
,都是在创建一个全新的、从未见过的视图控制器实例(在本例中为导航控制器(。该导航控制器与您试图忽略的属于当前选项卡的控制器无关。除了故事板中定义的根视图控制器之外,它的导航堆栈中没有其他内容。
您需要做的是在选项卡栏控制器的tabBarController(_:shouldSelect:)
方法中找到当前选项卡的导航控制器,并将该导航控制器传递给alertWasDismissed
闭包。
调用tabBarController(_:shouldSelect:)
方法时,选项卡栏控制器的selectedViewController
应包含当前视图控制器。将上面的行替换为:
if let navContr = tabBarController.selectedViewController? as? UINavigationController {}
这应该有效。