¿Cambiar a una vista de pestaña TabBar mediante programación?

159

Digamos que tengo una UIButtonvista en una pestaña en la aplicación de mi iPhone, y quiero que abra una pestaña diferente en la barra de pestañas del TabBarController. ¿Cómo escribiría el código para hacer esto?

Supongo que descargo la vista existente y cargo una vista de pestaña específica, pero no estoy seguro de cómo escribir el código exactamente.

Rottendevice
fuente
Tengo problemas con los métodos anteriores, muchachos me ayudan en mi [pregunta] [1] [1]: stackoverflow.com/questions/19742416/…
Roman Simenok

Respuestas:

399

Pruebe este código en Swift u Objective-C

Rápido

self.tabBarController.selectedIndex = 1

C objetivo

[self.tabBarController setSelectedIndex:1];
Jordán
fuente
8
Tenga en cuenta que, si el índice se asigna a una pestaña dentro del controlador de vista Más (si tiene más de cinco pestañas), esto no funcionará. En ese caso, use -setSelectedViewController:.
Joe D'Andrea
Después de hacer esto y cambiar las pestañas con éxito, ya no puedo seleccionar la barra de pestañas normalmente. ACTUALIZACIÓN: esto de alguna manera estaba relacionado con mi llamada a popToRootViewController justo antes de cambiar las pestañas mediante programación.
Adam Johns
Pero cómo Self no funcionará si quiero cambiar la pestaña. digamos que hago clic en la pestaña 3 y muestro alertView ahora cuando el usuario presiona ok, quiero cambiar a la pestaña 1 nuevamente. Self no tendrá razón ya que no es el objeto actual. Correcto?
Alix
Esto funciona bien, pero también tengo que pasar los datos al cambiar las pestañas. Tengo una etiqueta en la pestaña donde cambio a que necesita actualizarse tan pronto como cambie la pestaña. ¿Alguna solución fácil para esto?
Md Rais
@ AdamJohns ¿Cómo lograste resolver tu problema? para que se comporte como tabBar nativo. debería aparecer en rootViewController con el segundo clic.
Waqas
20

Tenga en cuenta que las pestañas se indexan a partir de 0. Entonces, el siguiente fragmento de código funciona

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

va a la quinta pestaña en la barra.

John Smith
fuente
12

Mi opinión es que selectedIndexo usar objectAtIndexno es necesariamente la mejor manera de cambiar la pestaña. Si reorganiza sus pestañas, una selección de índice codificada puede alterar su comportamiento anterior de la aplicación.

Si tiene la referencia de objeto del controlador de vista al que desea cambiar, puede hacer lo siguiente:

tabBarController.selectedViewController = myViewController

Por supuesto, debes asegurarte de que myViewControllerrealmente esté en la lista de tabBarController.viewControllers.

ThomasT
fuente
Necesitaba seleccionar másNavController y es la única forma de hacerlo hasta donde yo sé
Ossir
9

Simplemente puede establecer la selectedIndexpropiedad en UITabBarController en el índice apropiado y la vista cambiará al igual que el usuario presionó el botón de tabulación.

Alex Deem
fuente
66
La única diferencia es que no se llama al método de delegado que puede informar al usuario sobre el cambio de pestañas.
Brad The App Guy
3
La configuración selectedIndextampoco me funciona con índices> 4, pero selectedViewControllersí.
bugloaf
3

Intenté lo que sugirió Disco S2, estaba cerca pero esto es lo que terminó funcionando para mí. Esto se llamó después de completar una acción dentro de otra pestaña.

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

Para los casos en los que puede estar moviendo las pestañas, aquí hay un código.

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

Como la solución de Stuart Clark pero 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
}

Úselo así:

setTab(MyViewController.self)

Tenga en cuenta que mi tabController enlaza con viewControllers detrás de navigationControllers. Sin navigationControllers se vería así:

if let controller is T {
Json
fuente
Sin bucle, sin controladores de navegación: func selectViewController <ViewControllerModel> (tipo: ViewControllerModel.Type) {self.selectedViewController = self.viewControllers? .First (donde: {viewController en viewController es ViewControllerModel})}
dev_exo
1

Quería poder especificar qué pestaña se mostraba por clase en lugar de índice, ya que pensé que era una solución sólida que dependía menos de cómo conectaba el IB. No encontré las soluciones de Disco o Joped para trabajar, así que creé 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;
}

lo llamas así:

[self setTab:[YourClass class]];

Espero que esto sea útil para alguien

Stuart Clark
fuente
Esto funcionó muy bien! Lo reescribí para Swift3 en otra respuesta.
Json
1

Mi problema es un poco diferente, necesito cambiar de un childViewController en 1st tabBar a home viewController de 2nd tabBar. Simplemente uso la solución provista en el piso de arriba:

tabBarController.selectedIndex = 2

Sin embargo, cuando se cambió a la página de inicio de 2nd tabBar, el contenido es invisible. Y cuando depuro, viewDidAppear, viewWillAppear, viewDidLoad, ninguno de ellos se llama. Mi solución es agregar el siguiente código en el UITabBarController:

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

Uso en AppDelegate.marchivo:

(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
fuente
0

Como la solución de Stuart Clark, pero para Swift 3 y usando el identificador de restauración para encontrar la pestaña correcta:

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
}

Úselo de esta manera ("Humanos" y "Robots" también deben configurarse en el guión gráfico para viewController específico y su ID de restauración, o use el ID del guión gráfico y marque "usar ID del guión gráfico" como ID de restauración):

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

Tenga en cuenta que mi tabController enlaza con viewControllers detrás de navigationControllers. Sin navigationControllers se vería así:

if controller.restorationIdentifier == id {
Json
fuente
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
fuente
1
Por lo general, es mejor explicar una solución en lugar de solo publicar algunas filas de código anónimo. Puedes leer Cómo escribo una buena respuesta , y también Explicar respuestas completamente basadas en código
Anh Pham