Iphone 选择选项卡时弹出到根视图
我在一些我认为很容易的事情上遇到了一些麻烦。我的根视图控制器中有一个表,当选择一行时,我推送一个新视图,然后从那里转到另一个选项卡Iphone 选择选项卡时弹出到根视图,iphone,ios,uinavigationcontroller,uitabbarcontroller,Iphone,Ios,Uinavigationcontroller,Uitabbarcontroller,我在一些我认为很容易的事情上遇到了一些麻烦。我的根视图控制器中有一个表,当选择一行时,我推送一个新视图,然后从那里转到另一个选项卡 我的问题是如何确保一旦用户点击第一个选项卡,导航控制器就会弹出到root 你想做的事情听起来有点奇怪。您是否阅读了关于组合UINAVIgationController和UITABBARController的人机界面指南 [self.navigationController popToRootViewControllerAnimated:NO]; 但是,您需要做的是
我的问题是如何确保一旦用户点击第一个选项卡,导航控制器就会弹出到root 你想做的事情听起来有点奇怪。您是否阅读了关于组合UINAVIgationController和UITABBARController的人机界面指南
[self.navigationController popToRootViewControllerAnimated:NO];
但是,您需要做的是通过为UITabBarController设置代理并实现tabBarController:didSelectViewController:delegate方法来检测选项卡的选择。在此方法中,您需要使用UINavigationController的PoptorootViewController激活:方法弹出回根视图控制器。在选项卡栏上选择每个选项卡时,将调用以下委托
-(void) tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
将以下代码放入此委托方法中
if ([viewController isKindOfClass:[UINavigationController class]])
{
[(UINavigationController *)viewController popToRootViewControllerAnimated:NO];
}
在我的应用程序上运行良好。对于Swift爱好者:
import UIKit
class YourTabBarControllerHere: UITabBarController,
UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self;
}
func tabBarController(tabBarController: UITabBarController,
didSelectViewController viewController: UIViewController) {
if let vc = viewController as? UINavigationController {
vc.popViewControllerAnimated(animated: false);
}
}
}
编辑:Swift 3更新,感谢@Justin Oroz指出这一点。首先,您应该创建UITabbarController的子类并添加Observer:
- (void)viewDidLoad {
[super viewDidLoad];
[self.tabBar addObserver:self forKeyPath:@"selectedItem" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
}
当选择tabbar时,我们将使用以下方法处理:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if ([keyPath isEqualToString:@"selectedItem"] && [object isKindOfClass:[UITabBar class]]){
UITabBar *bar = (UITabBar *)object; // The object will be the bar we're observing.
// The change dictionary will contain the previous tabBarItem for the "old" key.
UITabBarItem *wasItem = [change objectForKey:NSKeyValueChangeOldKey];
NSUInteger was = [bar.items indexOfObject:wasItem];
// The same is true for the new tabBarItem but it will be under the "new" key.
UITabBarItem *isItem = [change objectForKey:NSKeyValueChangeNewKey];
NSUInteger is = [bar.items indexOfObject:isItem];
if (is == was) {
UIViewController *vc = self.viewControllers[is];
if ([vc isKindOfClass:[UINavigationController class]]) {
[(UINavigationController *)vc popToRootViewControllerAnimated:YES];
}
}
}
}
UTabController建议使用不同的UX,让用户“跳转到根目录”。当切换回选项卡时,它会保留以前的完整UINav堆栈。如果他们第二次点击条形图项目(点击所选的选项卡),它才会弹出到根目录。那都是自动的。有些应用程序,比如instagram,允许第三次点击滚动到顶部
我建议坚持默认设置,因为这是用户所期望的。下面的代码对我很有用。swift 3中的以下代码: 1> 子类UITabbarController并用一个iVAr实现下面两个方法:
类MyTabBarController:UITabBarController、UITabBarController Delegate{
var previousSelectedTabIndex:Int=-1
}
2> 在viewdidLoad中设置选项卡栏委托
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self // you must do it}
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
self.previousSelectedTabIndex = tabBarController.selectedIndex
}
func tabBarController(_ tabBarController: UITabBarController,
shouldSelect viewController: UIViewController) -> Bool {
if self.previousSelectedTabIndex == tabBarController.selectedIndex {
let nav = viewController as! UINavigationController // mine in nav_VC
for vc in nav.childViewControllers {
if vc is YUOR_DESIRED_VIEW_CONTROLLER {
nav.popToViewController(vc, animated: true)
return false// IT WONT LET YOU GO TO delegate METHOD
}
}
}
return true
}
tabBarController.selectedIndex为您提供所选选项卡
在tabBarController_shouldSelect_viewController method中,您可以通过一些简单的计算设置所需的视图控制器。如果您没有获得上述代码,请同时使用上述两种方法,并了解Swift 3.1中这两种方法是如何协同工作的 将UITabbarController delegate添加到TabBar类: 类YourClass:UITabBarController,UITabBarControllerDelegate{ 之后: 覆盖功能选项卡栏(选项卡栏:UITabBar,didSelectItem: (修道院院长){ }
Swift 4.2 我的解决方案是对UITabBarController进行子类化,并添加两个委托函数,如下所示:
import UIKit
class MyCustomTabBarController: UITabBarController, UITabBarControllerDelegate {
var previousSelectedTabIndex:Int = 0
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
self.previousSelectedTabIndex = tabBarController.selectedIndex
}
override func tabBar(_ tabBar: UITabBar, didSelect item:
UITabBarItem) {
let vc = self.viewControllers![previousSelectedTabIndex] as! UINavigationController
vc.popToRootViewController(animated: false)
}
}
确保将“动画”设置为false,否则将
Unbalanced calls to begin/end appearance transitions for the targeted ViewController
使用选定的视图控制器来创建popToRootViewController。基本上,您需要强制转换此实例 Swift
((selectedViewController) as! UINavigationController).popToRootViewController(animated: false)
//
// I just added extra line so the scroll bar won't annoy you.
试试这个
class TabBarClass: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
let vc = self.viewControllers![selectedIndex] as! UINavigationController
vc.popToRootViewController(animated: false)
}
}
Swift 5.1回答:
class YourTabBarName: UITabBarController, UITabBarControllerDelegate
{
override func viewDidLoad()
{
super.viewDidLoad()
self.delegate = self
}
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController)
{
if let vc = viewController as? UINavigationController
{ vc.popToRootViewController(animated: false) }
}
}
代码11.5,Swift 5:
您不需要使用两个委托方法。只有一个就足够了:
extension CustomTabBarController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if tabBarController.viewControllers?.firstIndex(of: viewController) == tabBarController.selectedIndex,
let navigationController = viewController as? UINavigationController {
navigationController.popToRootViewController(animated: true)
}
return true
}
}
如果你查看Apple的Phone.app,收藏夹和最近标签的行为与OP想要的是一样的。当你选择一个表行时,手机应用不会切换标签-这是我查询的行为,当用户点击不同的标签时,不会弹出根目录。啊,是的,OP的问题不完全是OP的意思“从那里我转到另一个选项卡"。用户是否选择了另一个选项卡或应用程序是否自动切换。这对我非常有帮助,可以根据我的要求在我的应用程序中正常工作。委托是什么文件?我尝试创建UINavigationController并将其指定为委托。我在viewDidLoad上看到它被调用,但将其指定为UITabBarDelegate或UITa的委托bBarControllerDelegate不调用此方法。我有点困惑。你能告诉我我在哪里添加此代码吗?对于那些无法使其不起作用的人,请尝试在头文件(.h)中添加
uitabarControllerDelegate
,并在实现文件(.m)中添加self.tabBarController.delegate=self;
。将“动画”更改为“否”实际上对我有帮助。当我将“动画”设置为“是”时,我的选项卡栏或导航控制器中的任何其他按钮都不起作用。当OP询问根控制器时,它应该是(在Swift 3语法中)vc.poptrootviewcontroller(动画:false)
此方法记录目标ViewController开始/结束外观转换的不平衡调用,即使它确实有效。我正在尝试找到一种不会记录错误的解决方案。
extension CustomTabBarController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if tabBarController.viewControllers?.firstIndex(of: viewController) == tabBarController.selectedIndex,
let navigationController = viewController as? UINavigationController {
navigationController.popToRootViewController(animated: true)
}
return true
}
}
//create a tabbar controller class set it to your TabbarController in storyboard
import UIKit
class MyTabbarViewController: UITabBarController,UITabBarControllerDelegate{
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController)
{
if let vc = viewController as? UINavigationController
{ vc.popToRootViewController(animated: false) }
}
}