iphone - ¿Cómo puedo detectar el descarte de un controlador de vista modal en el controlador de vista padre?
presentviewcontroller swift 4 (2)
Posible duplicado:
Función de llamada en ViewController subyacente como el controlador de vista modal se descarta
He intentado casi todo. Esto es lo que he intentado:
-(void)viewWillAppear:(BOOL)animated
{
NSLog(@"Test");
}
-(void)viewDidAppear:(BOOL)animated
{
NSLog(@"Test");
}
-(void)viewDidLoad
{
NSLog(@"Test");
}
¿Por qué ninguno de ellos funciona en mi controlador de vista padre cuando se descarta el controlador de vista modal? ¿Cómo puedo hacer que esto funcione?
La vista modal debería decirle a su padre que la descarte, entonces el padre sabrá porque es responsable de despedirlo.
Se puede ver un ejemplo de esto si crea un nuevo proyecto y elige la plantilla de Utility Application
.
Esta respuesta fue reescrita / expandida para explicar los 3 enfoques más importantes ( @galambalazs )
1. Bloques
El enfoque más simple es usar un block
devolución de llamada. Esto es bueno si solo tiene un oyente (el controlador de vista padre) interesado en el despido. Incluso puede pasar algunos datos con el evento.
En MainViewController.m
SecondViewController* svc = [[SecondViewController alloc] init];
svc.didDismiss = ^(NSString *data) {
// this method gets called in MainVC when your SecondVC is dismissed
NSLog(@"Dismissed SecondViewController");
};
[self presentViewController:svc animated:YES completion:nil];
En SecondViewController.h
@interface MainViewController : UIViewController
@property (nonatomic, copy) void (^didDismiss)(NSString *data);
// ... other properties
@end
En SecondViewController.m
- (IBAction)close:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
if (self.didDismiss)
self.didDismiss(@"some extra data");
}
2. Delegación
Delegation
es el patrón recomendado por Apple:
Descartar un controlador de vista presentado
Si el controlador de vista presentado debe devolver datos al controlador de vista que presenta, utilice el patrón de diseño de Delegation para facilitar la transferencia. La delegación facilita la reutilización de los controladores de vista en diferentes partes de su aplicación. Con delegación, el controlador de vista presentado almacena una referencia a un objeto delegado que implementa métodos desde un protocol formal. A medida que reúne los resultados, el controlador de vista presentado llama a esos métodos en su delegado. En una implementación típica, el controlador de vista presentador se convierte en el delegado de su controlador de vista presentado.
MainViewController
En MainViewController.h
@interface MainViewController : UIViewController <SecondViewControllerDelegate>
- (void)didDismissViewController:(UIViewController*)vc;
// ... properties
@end
En algún lugar de MainViewController.m (presentación)
SecondViewController* svc = [[SecondViewController alloc] init];
svc.delegate = self;
[self presentViewController:svc animated:YES completion:nil];
En otro lugar en MainViewController.m (se le informa sobre el despido)
- (void)didDismissViewController:(UIViewController*)vc
{
// this method gets called in MainVC when your SecondVC is dismissed
NSLog(@"Dismissed SecondViewController");
}
SecondViewController
En SecondViewController.h
@protocol SecondViewControllerDelegate <NSObject>
- (void)didDismissViewController:(UIViewController*)vc;
@end
@interface SecondViewController : UIViewController
@property (nonatomic, weak) id<SecondViewControllerDelegate> delegate;
// ... other properties
@end
En algún lugar de SecondViewController.m
[self.delegate didDismissViewController:self];
[self dismissViewControllerAnimated:YES completion:nil];
(nota: el protocolo con el método didDismissViewController: podría reutilizarse en toda la aplicación)
3. Notificaciones
Otra solución es enviar una NSNotification
. Este es un enfoque válido también, podría ser más fácil que delegar en caso de que solo desee notificar sobre el despido sin pasar demasiados datos. Pero su caso de uso principal es cuando desea múltiples oyentes para el evento de descarte (que no sea solo el controlador de vista principal).
¡Pero asegúrate de retirarte siempre de NSNotificationCentre una vez que hayas terminado! De lo contrario, corre el riesgo de bloquearse al recibir notificaciones incluso después de que se le desasigna. [Nota del editor]
En MainViewController.m
- (IBAction)showSecondViewController:(id)sender
{
SecondViewController *secondVC = [[SecondViewController alloc] init];
[self presentViewController:secondVC animated:YES completion:nil];
// Set self to listen for the message "SecondViewControllerDismissed"
// and run a method when this message is detected
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(didDismissSecondViewController)
name:@"SecondViewControllerDismissed"
object:nil];
}
- (void)dealloc
{
// simply unsubscribe from *all* notifications upon being deallocated
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)didDismissSecondViewController
{
// this method gets called in MainVC when your SecondVC is dismissed
NSLog(@"Dismissed SecondViewController");
}
En SecondViewController.m
- (IBAction)close:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
// This sends a message through the NSNotificationCenter
// to any listeners for "SecondViewControllerDismissed"
[[NSNotificationCenter defaultCenter]
postNotificationName:@"SecondViewControllerDismissed"
object:nil userInfo:nil];
}
¡Espero que esto ayude!