¿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.


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

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.


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.


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.


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

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

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 {

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


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
}

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;

    }

}

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 {

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
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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.