whose the not close iphone uiviewcontroller modal-dialog dismiss

iphone - the - ¿Desechando múltiples controladores de vista modal a la vez?



dismiss view controller swift 4 (5)

Aunque la respuesta aceptada funcionó para mí, puede estar desactualizada ahora y dejar una animación de aspecto extraño en donde el modal superior desaparecería de inmediato y la animación estaría en la vista modal posterior. Intenté muchas cosas para evitar esto y terminé teniendo que usar un poco de pirateo para que se viera bien. Nota: (solo probado en iOS8 +, pero debería funcionar con iOS7 +)

Básicamente, viewControllerA crea un UINavigationController con viewControllerB como rootview y lo presenta de manera modal.

// ViewControllerA.m - (void)presentViewB { ViewControllerB *viewControllerB = [[ViewControllerB alloc] init]; UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewControllerB]; navigationController.modalPresentationStyle = UIModalPresentationFormSheet; [self presentViewController:navigationController animated:YES completion:nil]; }

Ahora en viewControllerB vamos a presentar viewControllerC la misma manera, pero después de presentarlo, vamos a colocar una instantánea de viewControllerC sobre la capa de vista en el controlador de navegación de viewControllerB . Luego, cuando viewControllerC desaparece durante el despido, no veremos el cambio y la animación se verá hermosa.

//ViewControllerB.m - (void)presentViewC { ViewControllerC *viewControllerC = [[ViewControllerC alloc] init]; // Custom presenter method to handle setting up dismiss and snapshotting // I use this in a menu that can present many VC''s so I centralized this part. [self presentViewControllerForModalDismissal:viewControllerC]; }

A continuación, se encuentran las funciones de ayuda que se utilizan para presentar la vista y controlar la eliminación. Una cosa a tener en cuenta, estoy usando Purelayout para agregar restricciones de diseño automático. Puede modificar esto para agregarlos manualmente o obtener Purelayout en https://github.com/PureLayout/PureLayout

#pragma mark - Modal Presentation Helper functions - (void)presentViewControllerForModalDismissal:(UIViewController*)viewControllerToPresent { UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewControllerToPresent]; navigationController.modalPresentationStyle = UIModalPresentationFormSheet; // Ensure that anything we are trying to present with this method has a dismissBlock since I don''t want to force everything to inherit from some base class. NSAssert([viewControllerToPresent respondsToSelector:NSSelectorFromString(@"dismissBlock")], @"ViewControllers presented through this function must have a dismissBlock property of type (void)(^)()"); [viewControllerToPresent setValue:[self getDismissalBlock] forKey:@"dismissBlock"]; [self presentViewController:navigationController animated:YES completion:^{ // We want the presented view and this modal menu to dismiss simultaneous. The animation looks weird and immediately becomes the menu again when dismissing. // So we are snapshotting the presented view and adding it as a subview so you won''t see the menu again when dismissing. UIView *snapshot = [navigationController.view snapshotViewAfterScreenUpdates:NO]; [self.navigationController.view addSubview:snapshot]; [snapshot autoPinEdgesToSuperviewEdges]; }]; } - (void(^)()) getDismissalBlock { __weak __typeof(self) weakSelf = self; void(^dismissBlock)() = ^{ __typeof(self) blockSafeSelf = weakSelf; [blockSafeSelf.navigationController.presentingViewController dismissViewControllerAnimated:YES completion:nil]; }; return dismissBlock; }

Ahora solo tenemos que asegurarnos de que tenemos un despido de bloqueo definido como una propiedad en ViewControllerC.h (obviamente, puede reemplazar esta parte completa con métodos de delegado u otros patrones de diseño igualmente interesantes, la parte importante es manejar el despido en el nivel viewControllerB)

// ViewControllerC.h @interface ViewControllerC : UIViewController @property (nonatomic, copy) void (^dismissBlock)(void); @end //ViewControllerC.m // Make an method to handle dismissal that is called by button press or whatever logic makes sense. - (void)closeButtonPressed { if (_dismissBlock) {// If the dismissblock property was set, let the block handle dismissing _dismissBlock(); return; } // Leaving this here simply allows the viewController to be presented modally as the base as well or allow the presenter to handle it with a block. [self dismissViewControllerAnimated:YES completion:nil]; }

Espero que esto ayude, feliz programación :)

Entonces, tenga una pila con tres controladores de vista donde A es raíz, B es el primer controlador de vista modal y C es el tercer modal vc. Me gustaría ir de C a A de una vez. He intentado descartar esta solución . Funciona pero no de forma correcta. Es decir, cuando se descarta el último controlador de vista, se mostrará brevemente el segundo controlador de vista antes de que se muestre el primero. Lo que estoy buscando es una forma de pasar de la tercera animación a la primera en una buena animación sin notar la segunda vista. Cualquier ayuda en esto es muy apreciada.


Lo que quieres usar es popToRootViewControllerAnimated: Te lleva al controlador raíz sin mostrar todos los intermedios.


Para cualquier persona que busque un trabajo a su alrededor puede hacer esto:

  1. Cubre todo con una instantánea de la ventana.
  2. Descartar ambos controladores de vista sin animación.
  3. Presente una copia de la instantánea en otro controlador de vista sin animación.
  4. Retire la instantánea que cubre la ventana.
  5. Descartar el controlador de vista de instantánea con animación.

Aquí está el código:

let window = UIApplication.shared.keyWindow! let snapshot = window.snapshotView(afterScreenUpdates: false)! window.addSubview(snapshot) let baseViewController = self.presentingViewController!.presentingViewController! baseViewController.dismiss(animated: false) { let snapshotCopy = snapshot.snapshotView(afterScreenUpdates: false)! let snapshotViewController = UIViewController() snapshotViewController.view.addSubview(snapshotCopy) baseViewController.present(snapshotViewController, animated: false) { snapshot.removeFromSuperview() baseViewController.dismiss(animated: true, completion: nil) } }


Puede descartar estos modalViewControllers en su rootViewController.

UIViewController *viewController = yourRootViewController; NSMutableArray *array = [NSMutableArray array]; while (viewController.modalViewController) { [array addObject:viewController]; viewController = viewController.modalViewController; } for (int i = 0; i < array.count; i++) { UIViewController *viewController = array[array.count-1-i]; [viewController dismissModalViewControllerAnimated:NO]; }


Asegúrate de que solo llames a un dismissModalViewControllerAnimated: una vez.

Descubrí que pedir que se descarte cada controlador de vista modal apilados provocará que ambos se animen.

Tienes: A =modal> B =modal> C

Solo debes llamar [myViewControllerA dismissModalViewControllerAnimated:YES]

Si usa [myViewControllerB dismissModalViewControllerAnimated:YES] , descartará C, y no B. En uso normal (sin apilar), descartaría B (debido a que la cadena de respondedores está borrando el mensaje hasta A). En el escenario apilado que describe, B es un controlador de vista principal y esto tiene prioridad sobre ser un controlador de vista modal.