Mudando para uma exibição da guia TabBar programaticamente?

159

Digamos que eu tenha uma UIButtonvisualização em uma guia no meu aplicativo para iPhone e quero que ela abra uma guia diferente na barra de guias do TabBarController. Como eu escreveria o código para fazer isso?

Estou assumindo que descarrego a exibição existente e carrego uma exibição de guia específica, mas não sei como escrever o código exatamente.

rottendevice
fonte
Tenho problemas com métodos acima, caras de ajuda no meu [pergunta] [1] [1]: stackoverflow.com/questions/19742416/...
Roman Simenok

Respostas:

399

Experimente este código em Swift ou Objective-C

Rápido

self.tabBarController.selectedIndex = 1

Objetivo-C

[self.tabBarController setSelectedIndex:1];
Jordânia
fonte
8
Observe que, se o índice for mapeado para uma guia no controlador de exibição Mais (se você tiver mais de cinco guias), isso não funcionará. Nesse caso, use -setSelectedViewController:.
Joe D'Andrea
Depois de fazer isso e alterar as guias com êxito, não posso mais selecionar a barra de guias normalmente. UPDATE: de alguma forma, isso me chamou de popToRootViewController antes de eu trocar de guia programaticamente.
Adam Johns
Mas como o Self não funcionará se eu quiser mudar a guia. digamos que eu clique na guia 3 e mostre o alertView agora quando o usuário pressionar ok, desejo mudar para a guia 1 novamente. O eu não estará certo, pois não é o objeto atual. Correto?
Alix
Isso funciona bem, mas eu também tenho que passar os dados enquanto alterno as guias. Eu tenho um rótulo na guia onde eu mudo para que precisa ser atualizado assim que eu mudar a guia.! Alguma solução fácil para isso?
Md Ra
@AdamJohns Como você conseguiu resolver seu problema. para se comportar como tabBar nativo. ele deve aparecer no rootViewController no segundo clique.
Waqas
20

Observe que as guias são indexadas a partir de 0. Portanto, o seguinte snippet de código funciona

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

vai para a quinta aba no bar.

John Smith
fonte
12

Minha opinião é que selectedIndexou usar objectAtIndexnão é necessariamente a melhor maneira de mudar a guia. Se você reordenar suas guias, uma seleção de índice codificado pode interferir no comportamento anterior do aplicativo.

Se você tiver a referência de objeto do controlador de exibição para a qual deseja alternar, poderá:

tabBarController.selectedViewController = myViewController

Claro que você deve ter certeza de que myViewControllerrealmente está na lista de tabBarController.viewControllers.

ThomasT
fonte
Eu precisava para selecionar moreNavController e é a única maneira de fazer isso, tanto quanto eu sei
Ossir
9

Você pode simplesmente definir a selectedIndexpropriedade no UITabBarController para o índice apropriado e a exibição será alterada assim como o usuário tocou no botão tab.

Alex Deem
fonte
6
Com a pequena diferença, o método delegado que pode informar as guias de alternância do usuário não é chamado.
Brad The App Guy
3
Definir selectedIndextambém não funciona para mim com índices> 4, mas selectedViewControllerfunciona.
bugloaf
3

Eu tentei o que o Disco S2 sugeriu, estava próximo, mas foi o que acabou funcionando para mim. Isso foi chamado após a conclusão de uma ação dentro de outra guia.

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

Para os casos em que você pode mover as guias, aqui está um código.

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

Como a solução de Stuart Clark, mas para 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
}

Use-o assim:

setTab(MyViewController.self)

Observe que meu tabController está vinculado a viewControllers atrás de navigationControllers. Sem navigationControllers, ficaria assim:

if let controller is T {
Json
fonte
Sem loop, nenhum controlador de navegação: func selectViewController <ViewControllerModel> (tipo: ViewControllerModel.Type) {self.selectedViewController = self.viewControllers? .First (onde: {viewController no viewController é ViewControllerModel})}
dev_exo
1

Queria poder especificar qual guia foi mostrada por classe, em vez de indexar, pois achei que era uma solução robusta e menos dependente de como você conecta o IB. Não encontrei as soluções da Disco ou da Joped para funcionar, então criei este método:

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

você chama assim:

[self setTab:[YourClass class]];

Espero que isto ajude alguém

Stuart Clark
fonte
Isso funcionou muito bem! Reescrevi para o Swift3 em outra resposta.
Json 15/05
1

Meu problema é um pouco diferente. Preciso mudar de um childViewController no 1º tabBar para o home viewController do 2º tabBar. Simplesmente uso a solução fornecida no andar de cima:

tabBarController.selectedIndex = 2

No entanto, quando alternou para a página inicial da 2ª guiaBar, o conteúdo fica invisível. E quando depuro, viewDidAppear, viewWillAppear, viewDidLoad, nenhum deles é chamado. Minhas soluções é adicionar o seguinte código no UITabBarController:

override var shouldAutomaticallyForwardAppearanceMethods: Bool 
{
    return true
}
Jin
fonte
0

Use no AppDelegate.marquivo:

(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;

    }

}
Rakesh Singh
fonte
0

Como a solução de Stuart Clark, mas para Swift 3 e usando o identificador de restauração para encontrar a guia correta:

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
}

Use-o assim ("Humanos" e "Robôs" também devem ser definidos no storyboard para um viewController específico e seu ID de restauração, ou use o Storyboard ID e marque "use storyboard ID" como ID de restauração):

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

Observe que meu tabController está vinculado a viewControllers atrás de navigationControllers. Sem navigationControllers, ficaria assim:

if controller.restorationIdentifier == id {
Json
fonte
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)
}



}
Davender Verma
fonte
1
Geralmente, é melhor explicar uma solução em vez de apenas postar algumas linhas de código anônimo. Você pode ler Como redigir uma boa resposta e também Explicar respostas inteiramente baseadas em código
Anh Pham