web-dev-qa-db-fra.com

Comment puis-je détecter le rejet d'un contrôleur de vue modale dans le contrôleur de vue parent?

Duplicata possible:
La fonction d'appel dans ViewController sous-jacent en tant que contrôleur de vue modale est rejetée

J'ai essayé presque tout. Voici ce que j'ai essayé:

-(void)viewWillAppear:(BOOL)animated
{

NSLog(@"Test");

}

-(void)viewDidAppear:(BOOL)animated
{

NSLog(@"Test");

}

-(void)viewDidLoad
{

NSLog(@"Test");

}

Pourquoi aucun de ces éléments ne fonctionne-t-il dans mon contrôleur de vue parent lorsque le contrôleur de vue modal est fermé? Comment puis-je faire en sorte que cela fonctionne?

55
objc-obsessive

Cette réponse a été réécrite/développée pour expliquer les 3 approches les plus importantes ( @ galambalazs )

1. Blocs

L'approche la plus simple consiste à utiliser un rappel block . C'est bien si vous n'avez qu'un seul auditeur (le contrôleur de vue parent) intéressé par le licenciement. Vous pouvez même transmettre certaines données avec l'événement.

Dans 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];

Dans SecondViewController.h

@interface MainViewController : UIViewController
    @property (nonatomic, copy) void (^didDismiss)(NSString *data);
    // ... other properties
@end

Dans SecondViewController.m

- (IBAction)close:(id)sender 
{
    [self dismissViewControllerAnimated:YES completion:nil];

    if (self.didDismiss) 
        self.didDismiss(@"some extra data");
}

2. Délégation

Delegation est le modèle recommandé par Apple:

Rejet d'un contrôleur de vue présenté

Si le contrôleur de vue présenté doit renvoyer des données au contrôleur de vue présenté, utilisez le modèle de conception délégation pour faciliter le transfert. La délégation facilite la réutilisation des contrôleurs de vue dans différentes parties de votre application. Avec la délégation, le contrôleur de vue présenté stocke une référence à un objet délégué qui implémente des méthodes à partir d'un formel protocole . Lors de la collecte des résultats, le contrôleur de vue présenté appelle ces méthodes sur son délégué. Dans une implémentation typique, le contrôleur de vue présenté se fait le délégué de son contrôleur de vue présenté.

MainViewController

Dans MainViewController.h

@interface MainViewController : UIViewController <SecondViewControllerDelegate>
    - (void)didDismissViewController:(UIViewController*)vc;
    // ... properties
@end

Quelque part dans MainViewController.m (présentation)

SecondViewController* svc = [[SecondViewController alloc] init];
svc.delegate = self;
[self presentViewController:svc animated:YES completion:nil];

Quelque part ailleurs dans MainViewController.m (être informé du licenciement)

- (void)didDismissViewController:(UIViewController*)vc
{
    // this method gets called in MainVC when your SecondVC is dismissed
    NSLog(@"Dismissed SecondViewController");
}

SecondViewController

Dans SecondViewController.h

@protocol SecondViewControllerDelegate <NSObject>
- (void)didDismissViewController:(UIViewController*)vc;
@end

@interface SecondViewController : UIViewController
@property (nonatomic, weak) id<SecondViewControllerDelegate> delegate;
// ... other properties
@end

Quelque part dans SecondViewController.m

[self.delegate didDismissViewController:self];
[self dismissViewControllerAnimated:YES completion:nil];

(remarque: le protocole avec didDismissViewController: la méthode peut être réutilisée dans toute votre application)


3. Notifications

Une autre solution consiste à envoyer un NSNotification . C'est également une approche valide, elle pourrait être plus facile que la délégation au cas où vous ne voudriez que notifier au sujet du licenciement sans transmettre beaucoup de données. Mais son cas d'utilisation principal est lorsque vous voulez plusieurs écouteurs pour l'événement de rejet (autre que le contrôleur de vue parent).

Mais assurez-vous de toujours vous retirer de NSNotificationCentre une fois que vous avez terminé! Sinon, vous risquez de planter en étant appelé pour des notifications même après avoir été désalloué. [ndlr]

Dans 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");
}

Dans 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];
}

J'espère que cela t'aides!

119
Kiran Panesar

La vue modale devrait dire à son parent de le rejeter, alors le parent le saura car il est responsable de faire le rejet.

Un exemple de ceci peut être vu si vous créez un nouveau projet et choisissez le Utility Application modèle.

10
Paul.s