Переключение на представление вкладок TabBar программно?


159

Допустим, у меня есть приложение UIButtonс одной вкладкой в ​​приложении для iPhone, и я хочу, чтобы оно открывало другую вкладку на панели вкладок TabBarController. Как бы я написал код для этого?

Я предполагаю, что я выгружаю существующее представление и загружаю определенное представление вкладки, но я не уверен, как написать код точно.


У меня проблемы с методами, описанными выше, ребята, помогите в моем [вопросе] [1] [1]: stackoverflow.com/questions/19742416/…
Роман Сименок

Ответы:


399

Попробуйте этот код в Swift или Objective-C

стриж

self.tabBarController.selectedIndex = 1

Objective-C

[self.tabBarController setSelectedIndex:1];

8
Обратите внимание, что если индекс отображается на вкладку в контроллере представления Больше (если у вас более пяти вкладок), это не будет работать. В этом случае используйте -setSelectedViewController:.
Джо д'Андреа

После того, как я это сделал и он успешно меняет вкладки, я больше не могу нормально выбирать панель вкладок. ОБНОВЛЕНИЕ: это было как-то связано со мной, вызывающим popToRootViewController прямо перед тем, как я поменял вкладки программно.
Адам Джонс

Но как Self не будет работать, если я захочу переключить вкладку. скажем, я нажимаю на вкладку 3 и показываю alertView сейчас, когда пользователь нажимает ок, я хочу снова переключиться на вкладку 1. Сам не будет прав, поскольку это не текущий объект. Верный ?
Аликс

Это хорошо работает, но я также должен передавать данные при переключении вкладок. У меня есть ярлык на вкладке, где я переключаюсь на тот, который нужно обновить, как только я переключаю вкладку.! Любое простое решение этого?
Md Rais

@AdamJohns Как вам удалось решить вашу проблему. чтобы он вел себя как родной tabBar. он должен появиться в rootViewController при втором нажатии.
Waqas

20

Обратите внимание, что вкладки индексируются начиная с 0. Таким образом, работает следующий фрагмент кода

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

идет к пятой вкладке в панели.


12

Мое мнение таково, что selectedIndexиспользование objectAtIndexне обязательно является лучшим способом переключения вкладки. Если вы переупорядочиваете свои вкладки, выбор жестко закодированного индекса может испортить ваше прежнее поведение приложения.

Если у вас есть ссылка на объект контроллера представления, на который вы хотите переключиться, вы можете сделать:

tabBarController.selectedViewController = myViewController

Конечно, вы должны убедиться, что myViewControllerдействительно есть в списке tabBarController.viewControllers.


Мне нужно было выбрать moreNavController, и это единственный способ сделать это, насколько я знаю,
Ossir

9

Вы можете просто установить для selectedIndexсвойства UITabBarController соответствующий индекс, и представление будет изменено так же, как пользователь нажал кнопку вкладки.


6
Единственным небольшим отличием является то, что метод делегата, который может информировать пользователя о переключении вкладок, не вызывается.
Брэд App App Guy

3
Настройка selectedIndexтакже не работает для меня с индексами> 4, но selectedViewControllerработает.
bugloaf

3

Я попробовал то, что предложил Disco S2, это было близко, но это то, что в итоге сработало для меня. Это было вызвано после выполнения действия внутри другой вкладки.

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

2

Для случаев, когда вы можете перемещать вкладки, вот некоторый код.

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

2

Как и решение Стюарта Кларка, но для 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 ссылается на viewController за навигационными контроллерами. Без navigationControllers это выглядело бы так:

if let controller is T {

Без циклов нет контроллеров навигации: func selectViewController <ViewControllerModel> (type: ViewControllerModel.Type) {self.selectedViewController = self.viewControllers? .First (где: {viewController в viewController - это ViewControllerModel})}
dev_

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 в другом ответе.
Json

1

Моя проблема немного отличается, мне нужно переключиться с одного childViewController в 1-й tabBar на домашний viewController 2-й tabBar. Я просто использую решение, предоставленное наверху:

tabBarController.selectedIndex = 2

Однако, когда он переключился на домашнюю страницу 2-й вкладки, контент становится невидимым. И когда я отлаживаю, viewDidAppear, viewWillAppear, viewDidLoad, ни один из них не вызывается. Я решил добавить следующий код в UITabBarController:

override var shouldAutomaticallyForwardAppearanceMethods: Bool 
{
    return true
}

0

Использовать в AppDelegate.mфайле:

(void)tabBarController:(UITabBarController *)tabBarController
 didSelectViewController:(UIViewController *)viewController
{

     NSLog(@"Selected index: %d", tabBarController.selectedIndex);

    if (viewController == tabBarController.moreNavigationController)
    {
        tabBarController.moreNavigationController.delegate = self;
    }

    NSUInteger selectedIndex = tabBarController.selectedIndex;

    switch (selectedIndex) {

        case 0:
            NSLog(@"click me %u",self.tabBarController.selectedIndex);
            break;
        case 1:
            NSLog(@"click me again!! %u",self.tabBarController.selectedIndex);
            break;

        default:
            break;

    }

}

0

Как и решение Стюарта Кларка, но для Swift 3 и использования идентификатора восстановления, чтобы найти правильную вкладку:

private func setTabById(id: String) {
  var i: Int = 0
  if let controllers = self.tabBarController?.viewControllers {
    for controller in controllers {
      if let nav = controller as? UINavigationController, nav.topViewController?.restorationIdentifier == id {
        break
      }
      i = i+1
    }
  }
  self.tabBarController?.selectedIndex = i
}

Используйте его следующим образом («Люди» и «Роботы» также должны быть установлены в раскадровке для определенного viewController и его идентификатора восстановления, или используйте идентификатор раскадровки и отметьте «использовать идентификатор раскадровки» в качестве идентификатора восстановления):

struct Tabs {
    static let Humans = "Humans"
    static let Robots = "Robots"
}
setTabById(id: Tabs.Robots)

Обратите внимание, что моя tabController ссылается на viewController за навигационными контроллерами. Без navigationControllers это выглядело бы так:

if controller.restorationIdentifier == id {

0
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,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.