¿Cómo volver al controller de vista raíz pero luego presionar a una vista diferente?

Estoy escribiendo una aplicación simple que tiene 3 controlleres de vista. El controller de vista raíz es una item listing , vista de tabla básica. Fuera de este controller de vista, presiono dos controlleres de vista diferentes basados ​​en alguna interacción del usuario: un controller de vista de create item o un controller de view item vista.

Entonces, el storyboard segues se parece a un V, o algo así.

En mi controller de visualización de create item , quisiera que vuelva a aparecer en el controller de vista raíz cuando el usuario cree un elemento nuevo, pero luego presione el controller de view item para que pueda ver el elemento recién creado.

No puedo hacer que esto funcione. Es muy fácil volver al controller de vista raíz, pero no puedo presionar el controller de view item .

¿Algunas ideas? He pegado mi código, a continuación. La function pop funciona, pero la nueva vista nunca aparece.

 - (void) onSave:(id)sender { CLLocation *currentLocation = [[LocationHelper shanetworkingInstance] currentLocation]; // format the thread object dictionary NSArray* location = @[ @(currentLocation.coordinate.latitude), @(currentLocation.coordinate.longitude) ]; NSDictionary* thread = @{ @"title": _titleField.text, @"text": _textField.text, @"author": @"mustached-bear", @"location": location }; // send the new thread to the api server [[DerpHipsterAPIClient shanetworkingClient] postPath:@"/api/thread" parameters:thread success:^(AFHTTPRequestOperation *operation, id responseObject) { // init thread object Thread *thread = [[Thread alloc] initWithDictionary:responseObject]; // init view thread controller ThreadViewController *viewThreadController = [[ThreadViewController alloc] init]; viewThreadController.thread = thread; [self.navigationController popToRootViewControllerAnimated:NO]; [self.navigationController pushViewController:viewThreadController animated:YES]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { [self.navigationController popToRootViewControllerAnimated:YES]; }]; } 

Una manera fácil de lograr lo que quiere hacer es build una lógica simple en sus controlleres principales de vista raíz (void) viewWillAppear y usar una callback de delegado para voltear el interruptor lógico. básicamente una "reference de reference" al controller raíz. aquí hay un ejemplo rápido.

controller raíz principal (considere este controller a) – bien, llámelo controllerA configure una propiedad para realizar un seguimiento del estado del salto

 @property (nonatomic) BOOL jumpNeeded; 

Configurar alguna lógica en

 - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.jumpNeeded ? NSLog(@"jump needed") : NSLog(@"no jump needed"); if (self.jumpNeeded) { NSLog(@"jumping"); self.jumpNeeded = NO; [self performSegueWithIdentifier:@"controllerC" sender:self]; } } 

Ahora, en su controller raíz principal, cuando se selecciona una fila de vista de tabla haga algo como esto cuando se presiona a la controllera B en su tabla, se seleccionó el método

 [self performSegueWithIdentifer@"controllerB" sender:self]; 

luego implementa tu preparación para el método segue

 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { //setup controller B if([segue.identifier isEqualTo:@"controllerB"]){ ControllerB *b = segue.destinationViewController; b.delegate = self; //note this is the back reference } //implement controller c here if needed } 

Ahora muévase a controllerB, debe establecer una propiedad llamada "delegate" para retener la reference posterior y necesita importar el file de encabezado desde el controller raíz

 #import "controllerA" @property (nonatomic,weak) controllerA *delegate; 

luego, justo antes de regresar a la controlleraA, configura la bandera

  self.delegate.jumpNeeded = YES; [self.navigationController popViewControllerAnimated:YES]; 

Y eso es todo. No tiene que hacer nada con controllerC. Hay algunas otras forms de hacerlo, pero esto es bastante sencillo para sus necesidades. Espero que funcione para usted.

Si te comprendo correctamente, tienes una stack de controlleres de vista:

 A (root) - B - C - D - E 

Y quieres que se convierta en:

 A (root) - F 

¿Derecha? En ese caso:

 NSArray *viewControllers = self.navigationController.viewControllers; NSMutableArray *newViewControllers = [NSMutableArray array]; // preserve the root view controller [newViewControllers addObject:[viewControllers objectAtIndex:0]]; // add the new view controller [newViewControllers addObject:viewThreadController]; // animatedly change the navigation stack [self.navigationController setViewControllers:newViewControllers animated:YES]; 

creo
[self.navigationController pushViewController:viewThreadController animated:YES]; está utilizando un NavigationController diferente de la statement anterior. Porque después de aparecer en el controller de vista raíz, pierdes el controller de navigation en el que estás. Resuelve usar este código

 UINavigationController *nav = self.navigationController; [self.navigationController popToRootViewControllerAnimated:NO]; [nav pushViewController:viewThreadController animated:YES]; 

También creo que esto no resolverá todo su problema. Probablemente obtendrá un error que indica que dos pasos rápidos y empujones pueden invalidar el NavigationController.
Y para resolverlo, puede presionar el NavigationController en el método viewDidDissappear del segundo controller de vista o presionarlo en el método viewDidAppear en el controller de vista principal (listdo de elementos).

Compartir una categoría en UINavigationController basado en la respuesta de Dave DeLong que utilizamos en nuestra aplicación para mantener el button de retroceso siempre funcionando según sea necesario.

 @implementation UINavigationController (PushNewAndClearNavigationStackToParent) - (void) pushNewControllerAndClearStackToParent:(UIViewController*)newCont animated:(BOOL)animated {    NSArray *viewControllers = self.viewControllers;    NSMutableArray *newViewControllers = [NSMutableArray array];       // preserve the root view controller    [newViewControllers addObject:[viewControllers firstObject]];    // add the new view controller    [newViewControllers addObject:newCont];    // animatedly change the navigation stack    [self setViewControllers:newViewControllers animated:animated]; } @end 
 NSArray *viewControllers = self.navigationController.viewControllers; NSMutableArray *newViewControllers = [NSMutableArray array]; // preserve the root view controller for(int i = 0; i < [viewControllers count];i++){ if(i != [viewControllers count]-1) [newViewControllers addObject:[viewControllers objectAtIndex:i]]; } // add the new view controller [newViewControllers addObject:conversationViewController]; // animatedly change the navigation stack [self.navigationController setViewControllers:newViewControllers animated:YES]; 

No creo que esto sea posible porque reventar desasignará todo.

Creo que una mejor manera es poner sus datos en un model de class singleton, pop a rootviewcontroller y escuchar el pop para terminar. Luego, verifica si hay algunos datos almacenados en el model para saber si debe presionar un nuevo controller de vista.

Utilicé la respuesta de Dave como inspiración e hice esto para Swift:

 let newViewControllers = NSMutableArray() newViewControllers.addObject(HomeViewController()) newViewControllers.addObject(GroupViewController()) let swiftArray = NSArray(array:newViewControllers) as! Array<UIViewController> self.navigationController?.setViewControllers(swiftArray, animated: true) 
  1. Reemplace HomeViewController () con lo que desee que su controller de vista inferior sea
  2. Reemplace GroupViewController () con lo que desee que su controller de vista superior sea

Si lo que quiere hacer es navegar de cualquier manera dentro del mismo controller de navigation … puede acceder a los viewControllers de navigationStack AKA y luego establecer los controlleres de vista en el order que desee o agregar o eliminar algunos … Esto es lo más limpio y forma nativa de hacerlo.

  UINavigationController* theNav = viewControllerToDismiss.navigationController; UIViewController* theNewController = [UIViewController new]; UIViewController* rootView = theNav.viewControllers[0]; [theNav setViewControllers:@[ rootView, theNewController ] animated:YES]; 

haga las validaciones necesarias para que no obtenga ninguna exception.