2012-09-30 20 views
12

Estoy intentando convertir nuestra aplicación para guiones gráficos y he golpeado lo que creo que es un error en el manejo de segues de desenrollado cuando se trata de controladores contenedor personalizado. Tenemos un controlador de vista que muestra otro y usa la API de contención del controlador de vista para hacer esto, conecto el segue en IB y luego selecciono una clase personalizada para la implementación. El método de llevar a cabo es como la siguiente:No se puede crear desenrollado da paso al utilizar vista personalizada controlador de contención

-(void) perform { 
    UIViewController *container = [self sourceViewController]; 
    UIViewController *child = [self destinationViewController]; 
    [container addChildViewController:child]; 
    [container.view addSubview:child.view]; 
    child.view.center = container.view.center; 
    [UIView transitionWithView:container.view 
         duration:0.35 
         options:UIViewAnimationOptionCurveEaseInOut 
        animations:^{ 
         child.view.alpha = 1; 
        } completion:^(BOOL finished) { 
         [child didMoveToParentViewController:container]; 
        }]; 
} 

que funciona perfectamente, sin embargo no puedo hacerlo funcionar al segue desenrollado de vuelta al controlador contenedor. Puedo reemplazar viewControllerForUnwindSegueAction: fromViewController: withSender: y asegurarse de que es devolver el valor correcto:

-(UIViewController *) viewControllerForUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender { 
    id default = [super viewControllerForUnwindSegueAction:action fromViewController:fromViewController withSender:sender]; 
    NSAssert1(default == self, @"Expected the default view controller to be self but was %@", default); 
    return default; 
} 

También puedo confirmar que canPerformUnwindSegueAction: fromViewController: withSender se está llamando y haciendo lo correcto, pero para asegurarse de que los datos sobrescritos para volver SÍ

-(BOOL) canPerformUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender { 
    return YES; 
} 

El siguiente paso que se puede esperar que ocurra es segueForUnwindingToViewController: fromViewController: identificador: a llamarse, sin embargo nunca lo es. En cambio, la aplicación se bloquea con una NSInternalInconsistencyException.

segues de desenrollado
2012-10-01 10:56:33.627 UnwindSegues[12770:c07] *** Assertion failure in -[UIStoryboardUnwindSegueTemplate _perform:], /SourceCache/UIKit_Sim/UIKit-2372/UIStoryboardUnwindSegueTemplate.m:78 
2012-10-01 10:56:33.628 UnwindSegues[12770:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not find a view controller to execute unwinding for <USCustomContainerViewController: 0x75949a0>' 
*** First throw call stack: 
(0x1c8e012 0x10cbe7e 0x1c8de78 0xb61f35 0x581711 0x45ab54 0x10df705 0x16920 0x168b8 0xd7671 0xd7bcf 0xd6d38 0x4633f 0x46552 0x243aa 0x15cf8 0x1be9df9 0x1be9ad0 0x1c03bf5 0x1c03962 0x1c34bb6 0x1c33f44 0x1c33e1b 0x1be87e3 0x1be8668 0x1365c 0x1e7d 0x1da5) 
libc++abi.dylib: terminate called throwing an exception 

Alguien ha utilizado con éxito combinan con las APIs de vista del controlador de contención? ¿Alguna idea de qué paso me estoy perdiendo? Cargué un demo project to github que muestra el problema en el proyecto de demostración más simple que pude encontrar.

+0

Para referencia: http://openradar.appspot.com/radar?id=2144402 –

Respuesta

2

Esto parece ser un error - También esperaría descansar segues trabajar como ha implementado.

La solución que he usado se desestimó expresamente, el controlador de vista presentado en el método IBAction:

- (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController 
             fromViewController:(UIViewController *)fromViewController 
               identifier:(NSString *)identifier 
{ 
    return [[UIStoryboardSegue alloc] initWithIdentifier:identifier 
               source:fromViewController 
              destination:toViewController]; 
} 

- (IBAction)unwind:(UIStoryboardSegue*)segue 
{ 
    UIViewController *vc = segue.sourceViewController; 
    [vc willMoveToParentViewController:nil]; 
    if ([vc respondsToSelector:@selector(beginAppearanceTransition:animated:)]) { 
     [vc beginAppearanceTransition:NO animated:YES]; // iOS 6 
    } 
    UIView *modal = vc.view; 
    UIView *target = [[segue destinationViewController] view]; 
    [UIView animateWithDuration:duration animations:^{ 
     modal.frame = CGRectMake(0, target.bounds.size.height, modal.frame.size.width, modal.frame.size.height); 
    } completion:^(BOOL finished) { 
     [modal removeFromSuperview]; 
     [vc removeFromParentViewController]; 
     if ([vc respondsToSelector:@selector(endAppearanceTransition)]) { 
      [vc endAppearanceTransition]; 
      } 
    }]; 
} 
5

El problema en su ejemplo es que no hay allí existe. Es también simple. Primero, crea su controlador de vista de contenedor de una manera bastante extraña (no usa la nueva "vista de contenedor" de IB que está allí para ayudarlo a hacer esto). En segundo lugar, no tienes nada que relajar: nada fue presentado ni presentado por encima de nada.

Tengo un ejemplo de trabajo que muestra que canPerformUnwindSegueAction realmente se consulta a la cadena principal, y que viewControllerForUnwindSegueAction y segueForUnwindingToViewController se llaman y son efectivos, si están presentes en el lugar correcto. Ver:

https://github.com/mattneub/Programming-iOS-Book-Examples/tree/master/ch19p640presentedViewControllerStoryboard2

que tengo ahora también creó un tenedor de su original ejemplo en github, corregirlo de modo que ilustra estas características:

https://github.com/mattneub/UnwindSegues

No es realmente una situación donde "desenrollar" es necesaria , pero sí muestra cómo "relajarse" se puede utilizar cuando se trata de un controlador de vista contenedor personalizado.

+0

Supongo que el enlace debe ser https://github.com/mattneub/Programming-iOS-Book-Examples/tree/master/ ch19p640presentedViewControllerStoryboard2 Traté de editarlo, pero SO no me deja, ya que la edición tiene menos de 6 caracteres – combinatorial

+0

Lo arreglaré; Gracias por el aviso. – matt

+4

¡Qué mal que el enlace esté muerto! Realmente necesito la solución ... –

2

Breve historia antes de la respuesta: Me acabo de encontrar con el mismo mensaje de error exacto cuando se trata de utilizar múltiples puntos de vista de contenedores en una pantalla iPad en iOS 6 y llamando segues descansar de código.Al principio pensé que esto podría ser un problema porque mi transición se creó usando Storyboards arrastrando CTRL desde File Owner a Exit en lugar de desde UI control a Exit, pero obtuve los mismos resultados cuando puse Test Close Button en cada VC y tuve ellos desencadenan los desenrollamientos. Me di cuenta de que estoy tratando de desenrollar un segue de inserción, no un segue modal/push/popup, por lo que tiene sentido que no lo haga. Después de todo, si el segue de desenrollado tiene éxito y el controlador de vista se descarga desde una Vista de contenedor, iOS 6 cree que habrá un espacio vacío en la pantalla en ese punto. (En mi caso, tengo otra vista de contenedor ocupando la pantalla inmobiliaria que se muestra detrás de la vista del contenedor que estoy tratando de descargar, pero iOS no lo sabe porque los dos no están conectados de ninguna manera).

Respuesta: esto me llevó a darme cuenta de que solo puede desenrollar los modos modal, push o popover, ya sea dentro de la ventana principal o como parte de un controlador de navegación/pestaña. Esto es b/c iOS sabe entonces que hubo un VC anterior responsable de toda la pantalla y es seguro volver a ella. Entonces, en su caso, buscaría una forma de decirle a iOS que su vista de contenedor hijo está conectada a su vista de contenedor principal de forma que sea seguro descartar la vista de contenedor hijo. Por ejemplo, realice un segue modal/push/popover al mostrar la vista de contenedor hijo, o envuelva ambos en una clase UINavigationController personalizada (supongo que no desea la barra de navegación, por eso clase personalizada).

Lo siento, no puedo dar el código exacto, pero este es el mejor que he tenido hasta ahora y espero que sea útil.

0

Parece que este error está solucionado en iOS9.

+0

Esto debería ser un comentario. –

Cuestiones relacionadas