2011-12-24 15 views
23

Tengo una aplicación de iPhone que utiliza una implementación estándar de UINavigationController para la navegación de la aplicación.Reemplazar un UIViewController en la jerarquía UINavigationController

Estoy tratando de encontrar una manera de reemplazar un controlador de vista en la jerarquía. En otras palabras, mi aplicación se carga en un rootViewController y cuando el usuario presiona un botón, la aplicación presiona al firstViewController. Luego, el usuario presiona otro botón para navegar por la aplicación al secondViewController. Nuevamente el uso navega hacia abajo a otro controlador de vista, tercer ViewController. Sin embargo, quiero que el BackButton del thirdViewController vuelva a aparecer en firstViewController.

Esencialmente, cuando el usuario presiona a thirdViewController, me gustaría reemplazar secondViewController en la jerarquía de navegación.

¿Esto es posible? Sé que está usando Three20, pero no estoy en este caso. Sin embargo, si es posible en Three20, entonces ciertamente debería usar llamadas SDK directas. Alguien tiene alguna opinión?

Saludos, Brett

+0

también me gustaría ver en Unwind Segues, que son útiles para llevar a cabo este tipo de cosas. Awesome SO respuesta sobre ellos aquí: http://stackoverflow.com/questions/12561735/what-are-unwind-segues-for-and-how-do-you-use-them – jrisberg

+0

En el ejemplo dado, ¿no es cierto? simplemente pop (que se deshace del segundo), y luego push (ahora tiene 1-3). Alternativamente, si es un "botón diferente", cuando está en 1-2-3, simplemente aparece dos veces y estará en 1. – Fattie

Respuesta

41

bastante simple, al punto de empujar la thirdViewController en vez de hacer un simple pushViewController hacer esto:

NSArray * viewControllers = [self.navigationController viewControllers]; 
NSArray * newViewControllers = [NSArray arrayWithObjects:[viewControllers objectAtIndex:0], [viewControllers objectAtIndex:1], thirdController,nil]; 
[self.navigationController setViewControllers:newViewControllers]; 

donde [viewControllers objectAtIndex:0][viewControllers objectAtIndex:1] y son su RootViewController y su FirstViewController.

22
NSMutableArray *viewController = [NSMutableArray arrayWithArray:[navController viewControllers]]; 
[viewController replaceObjectAtIndex:1 withObject:replacementController]; 
[navController setViewControllers:viewController]; 

Ver el UINavigationController class reference para más información.

+0

Gracias, amigo. Esta solución lo manejó. Aclamaciones. – Felipe

4

No es posible animar la transición si simplemente reemplaza viewController en la matriz de controles de vista de los controladores de navegación. Recomendaría hacer lo siguiente en el método viewWillAppear del controlador de tercera vista.

-(void) viewWillAppear:(BOOL)animated 
{ 
    NSArray *vCs=[[self navigationController] viewControllers]; 
    NSMutableArray *nvCs=nil; 
    //remove the view controller before the current view controller 
    nvCs=[[NSMutableArray alloc]initWithArray:vCs]; 
    [nvCs removeObjectAtIndex:([nvCs count]-2)]; 
    [[self navigationController] setViewControllers:nvCs]; 
    [super viewWillAppear:animated]; 
} 
2

Puesto que usted está tratando de hacer estallar el doble de los ViewControllers pila, es probable que pueda obtener el mismo resultado llamando

- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated 

desde el botón de atrás de la thirdViewController

1
- (void)swapTopViewController:(UIViewController *)topViewController{ 
    NSArray *viewControllers = [self.navigationController viewControllers]; 
    NSMutableArray *editableViewControllers = [NSMutableArray arrayWithArray:viewControllers]; 
    [editableViewControllers removeLastObject]; 
    [editableViewControllers addObject:topViewController]; 
    [self.navigationController setViewControllers:editableViewControllers]; 
} 
0

Versión de Swift 2.2:

if var viewControllers = navigationController?.viewControllers { 
    viewControllers[viewControllers.count - 1] = newViewController 
    navigationController?.viewControllers = viewControllers 
} 
2

una forma más limpia en Swift debe ser:

extension UINavigationController { 
    func replaceTopViewController(with viewController: UIViewController, animated: Bool) { 
    var vcs = viewControllers 
    vcs[vcs.count - 1] = viewController 
    setViewControllers(vcs, animated: animated) 
    } 
} 
1
extension UINavigationController { 

    func setTop(viewController: UIViewController) { 
     viewControllers = [viewController] 
    } 

} 
+0

¿No sería eso eliminarlos a todos, y dejar solo el uno? – Fattie

+0

@Fattie yep. Lo cual sería suficiente para el escenario OP. Esta función establece el controlador de vista superior. Si no quieres ese comportamiento, entonces necesitarías una función diferente. – Harris

+1

Entendido. lindas cosas. – Fattie

Cuestiones relacionadas