Desplazamiento personalizado segue animation

Tengo la siguiente configuration:

Idea de instalación

El controller rojo tiene un método

- (IBAction)unwindToRed:(UISegue *)segue 

y un

 - (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier 

que devuelve un segue personalizado para este evento.

En mi segue personalizado tengo lo siguiente en el código de ejecución:

 - (void)perform { // Just helpers to get the controllers from the segue UIViewController *destination = self.destinationViewController; UIViewController *source = self.sourceViewController; // Setting transitioning delegate for custom transitions destination.transitioningDelegate = self; source.transitioningDelegate = self; destination.modalTransitionStyle = UIModalPresentationCustom; source.modalPresentationStyle = UIModalPresentationCurrentContext; // When I am transitioning to a new one if(!self.reversed) { [source presentViewController:destination animated:YES completion:nil]; } // Or reversing from a current one else { [source dismissViewControllerAnimated:YES completion:nil]; } } 

Como puede ver, he configurado un delegado de transición que, a su vez, llama

 - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext 

en un controller de animation donde aplique mi animation personalizada. Pero ahora cuando presiono Unwind to Red en la vista amarilla, solo "desenrolla" a su elemento primario. (por ejemplo, el azul).

Cuando dejo la segue personalizada fuera de la ecuación, funciona bien. Va por el path a la cima.

Ahora creo que esto tiene que ver con el

 [source dismissViewControllerAnimated:YES]; 

línea, ya que por lo general solo va "una vez", mi pregunta es, ¿creo, a qué debo llamar allí para que llegue hasta rojo cuando sea necesario? El amarillo es una superposition modal. Entonces, "pop too root" no funcionaría.

Especificación de una Segue personalizada

La solución era utilizar una segue personalizada para el desenrollo. Lamentablemente, no puede especificar una segue personalizada para desenrollarse en el generador de interfaces como puede en una segue normal. Tienes que especificarlo con código.

Existe una function en UIViewController que puede anular llamada segueForUnwindingToViewController que especifica qué segue usar para desenrollar. La parte difícil es saber qué controller de vista anulará esta function. La respuesta es hacerlo en el padre de los controlleres de vista que está realizando la transición hacia / desde. En mi caso es el UINavigationController . El controller de navigation es el controller de vista de contenedor para el primer y tercer controller de vista. Si hubiera integrado controlleres de vista secundarios en mis vistas, la respuesta no sería el controller de navigation, sino el controller de vista principal.

Cree un controller de navigation personalizado henetworkingando de UINavigationController . Luego, asegúrese de configurar la class personalizada de su controller de navigation en el generador de interfaces. Ahora puede anular la function segueForUnwindingToViewController . Aquí hay una implementación mínima.

 class MyNavigationController: UINavigationController { override func segueForUnwindingToViewController(toViewController: UIViewController, fromViewController: UIViewController, identifier: String?) -> UIStoryboardSegue { return UIStoryboardSegue(identifier: identifier, source: fromViewController, destination: toViewController) } } 

Agregar animation a Segue personalizado

 override func segueForUnwindingToViewController(toViewController: UIViewController, fromViewController: UIViewController, identifier: String?) -> UIStoryboardSegue { return UIStoryboardSegue(identifier: identifier, source: fromViewController, destination: toViewController) { let fromView = fromViewController.view let toView = toViewController.view if let containerView = fromView.superview { let initialFrame = fromView.frame var offscreenRect = initialFrame offscreenRect.origin.x -= CGRectGetWidth(initialFrame) toView.frame = offscreenRect containerView.addSubview(toView) // Being explicit with the types NSTimeInterval and CGFloat are important // otherwise the swift compiler will complain let duration: NSTimeInterval = 1.0 let delay: NSTimeInterval = 0.0 let options = UIViewAnimationOptions.CurveEaseInOut let damping: CGFloat = 0.5 let velocity: CGFloat = 4.0 UIView.animateWithDuration(duration, delay: delay, usingSpringWithDamping: damping, initialSpringVelocity: velocity, options: options, animations: { toView.frame = initialFrame }, completion: { finished in toView.removeFromSuperview() if let navController = toViewController.navigationController { navController.popToViewController(toViewController, animated: false) } }) } } } 

Los detalles son de esta publicación.

Desea utilizar popToViewController del controller de navigation:

  [source.navigationController popToViewController:destination animated:YES]; 

o, use animated:NO y coloque todo en un bloque de animation: por ejemplo:

 UIViewAnimationOptions animation = UIViewAnimationOptionTransitionFlipFromRight | UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowAnimatedContent; UIViewController *source = (UIViewController *) self.sourceViewController; UIViewController *dest = (UIViewController *) self.destinationViewController; [UIView transitionWithView:src.navigationController.view duration:0.4 options: animation animations:^{ [source.navigationController popToViewController:dest animated:NO]; } completion:^(BOOL finished) { }]; 
  1. Verifique su implementación de UIStoryboardSegue . ¿Tu uso de modalTransitionStyle un error tipográfico en tu publicación o en tu código real? Corregido:

     destination.modalPresentationStyle = UIModalPresentationCustom; 
  2. También he tenido éxito sin escribir un UIStoryboardSegue personalizado. Intente vincular un método de acción del button "desenrollar al rojo" a un método vacío -unwindToRed: sin anular -segueForUnwindingToViewController: (por ejemplo, CTRL + arrastre del button en el VC azul al glifo "Salir" del VC azul en IB y select -unwindToRed: de la list.)

  3. Si el n. ° 2 no descarta el VC azul, podría intentar invocar manualmente el siguiente método en el -unwindToRed: IBAction:

     [self dismissViewControllerAnimated:NO completion:nil];