Controlador de barra de pestañas dentro de un controlador de navegación, o compartir una vista raíz de navegación

80

Estoy tratando de implementar una interfaz de usuario estructurada como en la aplicación Tweetie , que se comporta así: el controlador de vista de nivel superior parece ser un controlador de navegación, cuya vista raíz es una vista de tabla "Cuentas". Si hace clic en cualquier cuenta, pasa al segundo nivel, que tiene una barra de pestañas en la parte inferior. Cada elemento de la pestaña muestra una lista diferente y le permite profundizar más (los niveles posteriores no muestran la barra de pestañas).

Entonces, esto parece que la jerarquía de implementación es:

  • UINavigationController
    1. Cuentas :UITableViewController
    2. UITabBarController
      1. Tweets :UITableViewController
        • Vista detallada de un tweet / usuario / etc.
      2. Respuestas :UITableViewController
      3. ...

Esto parece funcionar [^ 1], pero parece no ser compatible según la documentación del SDK para -pushViewController:animated: (énfasis agregado):

viewController : el controlador de vista que se inserta en la pila.No puede ser una instancia del controlador de la barra de pestañas.

Me gustaría evitar las API privadas y similares, pero no estoy seguro de por qué este uso está explícitamente prohibido incluso cuando parece funcionar bien. ¿Alguien sabe la razón?

He pensado en poner el controlador de la barra de pestañas como el controlador principal, con cada una de las pestañas que contienen controladores de navegación separados. El problema con esto es que cada controlador de navegación necesita compartir un solo controlador de vista raíz (es decir, la tabla "Cuentas" en Tweetie ); esto no parece funcionar: empujar el controlador de la tabla a un segundo controlador de navegación parece eliminarlo desde el principio. Sin mencionar toda la contabilidad al seleccionar una cuenta diferente probablemente sería una molestia.

¿Cómo debo implementar esto de la manera correcta?

[^ 1]: El controlador de la barra de pestañas debe tener una subclase para que el elemento de navegación del controlador de la barra de pestañas en ese nivel permanezca sincronizado con el elemento de navegación de la pestaña seleccionada, y la necesidad del controlador de la tabla de la pestaña individual para enviar sus respectivas vistas de detalle a en self.tabBarController.navigationControllerlugar de self.navigationController.

Daniel Dickison
fuente

Respuestas:

63

Las dos respuestas anteriores lo hicieron bien: no uso UITabBarControlleren Tweetie. Es bastante fácil escribir una personalizada XXTabBarController(subclase simple de UIViewController) que esté feliz de ser empujada a una pila de controladores de navegación, pero que aún viva según la filosofía del "controlador de vista". Cada "pestaña" en la vista específica de la cuenta ( Tweets/ Replies/ Messages) es su propio controlador de vista, y en lo que a ellos respecta, están siendo intercambiados en la pantalla por un simple ol UITabBarController.

Loren
fuente
2
¿Cómo maneja su clase de controlador de barra de pestañas personalizada la plomería para las propiedades navigationItem y navigationController de sus controladores secundarios?
bvanderveen
¿Ha cambiado esto en iOS 5? Parece que puedo agregar un UITabBarController en un UINavigationController sin demasiado problema, incluso como controlador raíz.
sparkFinder
33

Estoy creando una aplicación que usa un marco de navegación similar al de Tweetie. Escribí una publicación sobre cómo hacer esto en mi blog www.wiredbob.com que también enlaza con el código fuente. Es una plantilla completa que puede tomar y usar como base para otro proyecto. ¡Buena suerte!

Robert Conn
fuente
10
Para aquellos que se preguntan, el enlace a la publicación de blog mencionada es wiredbob.com/blog/2009/4/20/…
Anh
@Robert Conn, muy buen tutorial. Estoy usando su concepto, pero por alguna razón mi tabBar no está activo. ¿Le sucedió esto cuando estaba implementando su aplicación?
A Salcedo
@ASalcedo: Yo también tuve este problema, pero descubrí que era porque necesitaba reducir el tamaño de las vistas asociadas con los elementos de la barra de pestañas, el tamaño de altura predeterminado de 460 era demasiado grande, en el código fuente en www.wiredbob.com verá que la altura establecida para los elementos de la pestaña es 369 para permitir la barra de pestañas. Para cambiar la altura en el generador de interfaces, también debe asegurarse de que el estado, la barra superior e inferior estén todos configurados en ninguno en el inspector de atributos de la vista (no es obvio de inmediato).
Izac
2
La publicación del blog está muerta para mí, ¿hay alguna posibilidad de que alguien tenga eso por ahí?
Tiago Veloso
enlace de publicación de blog de trabajo: wiredbob.com/2009/04/iphone-tweetie-style-navigation.html
oluckyman
10

Es posible agregar un UITabBar a cualquier UIViewController. De esa manera, en realidad no tiene que impulsar un UITabBarController y, por lo tanto, permanecer dentro de las pautas de la API de Apple.

En el constructor de interfaces, UITabBar se encuentra en "Ventanas, vistas y barras" en la biblioteca Cocoa Touch.

Himadri Choudhury
fuente
1
¡Hola! @Himadri Choudhury, ¿puede explicar "y por lo tanto mantenerse dentro de las pautas de la API de Apple", o dar la referencia? No puedo encontrar dónde se dice esta guía (no dudo que exista, pero no puedo encontrar la URL). Muchas gracias
darksider
10

Hago esto en un par de mis aplicaciones. El truco para agregar una barra de pestañas a una aplicación basada en navigationController es NO usar un TabBarController. Agregue una barra de pestañas a la vista, haga que el controlador de vista para esa vista sea un TabBarDelegate y responda a las selecciones del usuario en la barra de pestañas en el código del controlador de vista.

Uso las barras de pestañas para agregar vistas adicionales a la vista de la barra de pestañas como sub-vistas, para recargar una vista de tabla con diferentes conjuntos de datos, para recargar un UIPickerView, etc.

Alpinista
fuente
6

Estuve luchando durante la última hora para implementar un UITabBarporque se ocultaba cuando intentaba mostrar mi vista; entonces encontré esta publicación :

Básicamente, asegúrese de insertar su nueva vista debajo de la barra de pestañas, según esta línea de código:

[self.view insertSubview:tab2ViewController.view belowSubview:myTabBar];
esilver
fuente
Gracias, esto ayudó a arreglar mi barra de pestañas que desaparece. Utilicé el mismo código que propuso Robert Conn, pero de alguna manera la barra de pestañas de la interfaz de usuario desaparece cuando cambio a la segunda vista.
Vijay Katam
3

En mi aplicación, el controlador de vista raíz es un controlador UINavigation. En cierto punto de la aplicación, necesito mostrar un UITabBar. Intenté implementar un UITabBar en un UIView dentro de la jerarquía de navegación, como sugirieron algunas de las publicaciones anteriores, y esto funciona. Pero descubrí que quería más del comportamiento predeterminado que proporciona el controlador de pestañas y encontré una manera de usar UITabBarController con el controlador UINavigation:

1) Cuando quiero mostrar la vista de UITabBarController, hago esto:

MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.window.rootViewController = myUiTabBarControllerInstance;

2) Cuando quiero volver a donde estaba en la jerarquía de navegación, hago esto:

appDelegate.window.rootViewController = myNavControllerInstance;
richardsun
fuente
3

Esto podría lograrse simplemente integrando TabBarController en el controlador de navegación. En el guión gráfico:

  1. Arrastra un ViewController
  2. Haga clic en la escena de ViewController
  3. Haga clic en editor >> Insertar en >> Controlador de navegación.
  4. Arrastre un botón en el mismo ViewController.
  5. Arrastra un TabBarController
  6. Conecte el botón del ViewController al TabBarController mediante push Segue Action.

En este caso, solo el RootViewController de TabBarController estaría en la pila del controlador de navegación. Todos los TabBarItems tendrían la barra de navegación en la parte superior y el usuario puede ir a la pantalla de inicio en cualquier momento, independientemente del TabBarItem seleccionado

Esto se puede hacer en cualquier ViewController de la pila del controlador de navegación.

Si funciona, sugiéreme cómo aumentar la reputación para que pueda publicar las imágenes y el código en la siguiente respuesta. :)

caffieneToCode
fuente
3

Así es como lo hice. En realidad, esto es empujar un controlador de barra de pestañas al controlador de navegación. Funciona bien. No encontré en ninguna parte de la documentación que Apple no admita de esta manera. ¿Alguien puede darme un enlace a esta advertencia?

Si esto es cierto, ¿es posible que Apple se niegue a publicar mi aplicación en la tienda de aplicaciones?

-(void)setArrayAndPushNextController
{
    MyFirstViewController *myFirstViewController = [[MyFirstViewController alloc] init];
    MySecondViewController *mySecondViewController = [[MySecondViewController alloc] init];

    myFirstViewController.array = self.array;


    NSArray *array = [[NSArray alloc] initWithObjects:myFirstViewController, mySecondViewController, nil];
    UITabBarController *tab = [[UITabBarController alloc] init];
    tab.viewControllers = array;

    [array release];

    UITabBarItem *item1 = [[UITabBarItem alloc] initWithTitle:@"first title" image:nil tag:1];
    UITabBarItem *item2 = [[UITabBarItem alloc] initWithTitle:@"second title" image:nil tag:2];

    myFirstViewController.tabBarItem = item1;
    mySecondViewController.tabBarItem = item2;

    [self stopAnimatingSpinner];

    [self.navigationController pushViewController:tab animated:YES];

    [tab release];
    [item1 release];
    [item2 release];
}
savudin
fuente
olvidó liberar sus UIViewControllers
Gargo