以编程方式切换到TabBar选项卡视图?

173
假设我在iPhone应用程序的一个选项卡视图中有一个UIButton,并且我想让它打开TabBarController标签栏中的另一个选项卡。 我该如何编写代码来实现这一点?
我假设我要卸载现有视图并加载特定的选项卡视图,但我不确定如何编写代码。

我在上面的方法中遇到了问题,大家可以在我的问题中帮忙吗? - Roman Simenok
12个回答

427

请使用以下的Swift或Objective-C代码进行尝试

Swift

self.tabBarController.selectedIndex = 1

Objective-C

[self.tabBarController setSelectedIndex:1];

9
请注意,如果索引映射到More视图控制器中的选项卡(如果您有超过五个选项卡),则此方法将无法正常工作。在这种情况下,请使用“-setSelectedViewController:”方法。 - Joe D'Andrea
在我执行这个操作并成功切换选项卡后,我无法再正常选择选项卡栏。更新:这似乎与我在编程中调用popToRootViewController有关,就在我交换选项卡之前。 - Adam Johns
但是如果我想要切换选项卡,Self怎么办呢?比如说我点击了选项卡3并显示alertView,现在当用户按下“确定”后,我想再次切换到选项卡1。Self不正确,因为它不是当前对象。对吗? - Alok C
这个功能很好,但我在切换选项卡时也必须传递数据。我在要切换到的选项卡中有一个标签,需要在我切换选项卡时立即更新它。有什么简单的解决方案吗? - Md Rais
@AdamJohns 你是怎么解决你的问题的?让它表现得像原生的 tabBar,第二次点击应该弹回到 rootViewController。 - Waqas

20

请注意,标签页的索引从0开始计数。因此,以下代码片段可以正常工作:

tabBarController = [[UITabBarController alloc] init];
.
.
.
tabBarController.selectedViewController = [tabBarController.viewControllers objectAtIndex:4];

跳转到标签栏中的第五个标签。


13

我的观点是,selectedIndex或使用objectAtIndex并不一定是切换选项卡的最佳方式。如果您重新排列选项卡,则硬编码的索引选择可能会影响您以前的应用程序行为。

如果您有要切换到的视图控制器的对象引用,可以执行以下操作:

tabBarController.selectedViewController = myViewController

当然,你必须确保 myViewController 真的在 tabBarController.viewControllers 的列表中。


我需要选择更多的NavController,据我所知这是唯一的方法。 - Ossir
是的,这个答案让我从一个几乎无法解释的故障中解脱了出来!非常感谢你! - Johan Albrectsen

9
您可以简单地将UITabBarController上的selectedIndex属性设置为适当的索引,视图将会像用户点击选项卡按钮一样更改。

6
唯一的小区别在于无法调用可通知用户切换选项卡的委托方法。 - Brad The App Guy
3
我无法使用大于4的索引来设置“selectedIndex”,但是可以使用“selectedViewController”来实现。 - bugloaf

3

我尝试了Disco S2建议的方法,它很接近但最终这是对我有用的。这是在另一个选项卡内完成操作后调用的。

for (UINavigationController *controller in self.tabBarController.viewControllers)
{
    if ([controller isKindOfClass:[MyViewController class]])
    {
        [self.tabBarController setSelectedViewController:controller];
        break;
    }
}

3

像 Stuart Clark 的解决方案一样,但适用于 Swift 3:

func setTab<T>(_ myClass: T.Type) {
    var i: Int = 0
    if let controllers = self.tabBarController?.viewControllers {
        for controller in controllers {
            if let nav = controller as? UINavigationController, nav.topViewController is T {
                break
            }
            i = i+1
        }
    }
    self.tabBarController?.selectedIndex = i
}

使用方法如下:

setTab(MyViewController.self)

请注意,我的tabController链接到导航控制器后面的视图控制器。如果没有导航控制器,它会像这样:
if let controller is T {

不使用循环,也没有导航控制器:func selectViewController<ViewControllerModel>(type:ViewControllerModel.Type) { self.selectedViewController = self.viewControllers?.first(where: { viewController in viewController is ViewControllerModel }) } - dev_exo

3

我的问题略有不同,我需要从第一个标签栏中的一个子视图控制器切换到第二个标签栏的主页视图控制器。我只需使用楼上提供的解决方案:

tabBarController.selectedIndex = 2

然而,当它切换到第二个标签栏的主页时,内容是不可见的。当我进行调试时,viewDidAppear、viewWillAppear和viewDidLoad都没有被调用。

我的解决方案是在UITabBarController中添加以下代码:

override var shouldAutomaticallyForwardAppearanceMethods: Bool 
{
    return true
}

2

如果您需要移动标签页,这里是一些代码。

for ( UINavigationController *controller in self.tabBarController.viewControllers ) {
            if ( [[controller.childViewControllers objectAtIndex:0] isKindOfClass:[MyViewController class]]) {
                [self.tabBarController setSelectedViewController:controller];
                break;
            }
        }

1
import UIKit

class TabbarViewController: UITabBarController,UITabBarControllerDelegate {

//MARK:- View Life Cycle

override func viewDidLoad() {
    super.viewDidLoad()

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()

}

//Tabbar delegate method
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
    let yourView = self.viewControllers![self.selectedIndex] as! UINavigationController
    yourView.popToRootViewController(animated:false)
}



}

1
通常最好解释一下解决方案,而不仅仅是发布一些匿名代码行。您可以阅读《如何撰写良好的答案》和《解释完全基于代码的答案》。 - Anh Pham
太好了!如果您需要在另一个视图控制器覆盖时“重新单击”已打开的选项卡,则可以这样做。 - djdance

1

我希望能够通过类而不是索引来指定要显示的选项卡,因为我认为这样可以提供一个更健壮的解决方案,减少对IB连接方式的依赖。我发现Disco和Joped的解决方案都无法正常工作,因此我创建了这个方法:

-(void)setTab:(Class)class{
    int i = 0;
    for (UINavigationController *controller in self.tabBarContontroller.viewControllers){
        if ([controller isKindOfClass:class]){
            break;
        }
        i++;
    }
    self.tabBarContontroller.selectedIndex = i;
}

你可以这样调用:

[self setTab:[YourClass class]];

希望这对某些人有所帮助。

这个很棒!我在另一个答案中用Swift3重写了它。 - Paintoshi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接