web-dev-qa-db-fra.com

Comment supprimer 2 contrôleurs de vue modale en succession?

J'ai 2 contrôleurs de vue présentés modalement.

A presents B which presents C.

Lorsque je rejette C, je voudrais également rejeter B. Mais je ne sais pas comment faire cela:

Rejeter C:

[self dismissModalViewControllerAnimated:YES]
//[delegate dismissB] //this doesn't work either when i create a delegate pattern

Maintenant, je reste avec B. Comment puis-je écarter B de C?

34
Sheehan Alam

Essayez d’utiliser le code suivant dans B (juste après avoir supprimé C, comme vous le faites déjà):

[self.parentViewController dismissModalViewControllerAnimated:YES];

IMPORTANT:
Ne faites rien dans la méthode après cette ligne.
Ce contrôleur de vue (B) sera probablement publié et désalloué ...

METTRE À JOUR:
À partir de iOS7, la méthode ci-dessus est obsolète.
Utilisez la méthode suivante à la place:

[self.parentViewController dismissViewControllerAnimated:YES completion:^{ /* do something when the animation is completed */ }];
9
Michael Kessler

Je viens de découvrir que vous devez utiliser présenterViewController dans iOS 5.

[self.presentingViewController.presentingViewController dismissModalViewControllerAnimated:YES];

A -> B -> C

Exécuter le code ci-dessus en modal C vous ramènera à A

106
Andy Davies

Cela a fonctionné pour moi, très simple

// Call inside View controller C    
self.presentingViewController?.dismissViewControllerAnimated(false, completion: nil)
self.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)

Explication: 

Si vous appelez licenciement sur C, il ne peut supprimer que C. Si vous appelez licencié sur B, vous ferez bien: Supprimez le plus haut contrôleur de vue modale. Le premier appel supprime donc C (sans animation). Le deuxième appel supprime B. 

Le moyen le plus simple d'accéder au contrôleur de vue B à partir de C consiste à utiliser la variable présentantViewViewController. 

14
n13

En B. Mettez:

[self dismissModalViewControllerAnimated:NO];
[self dismissModalViewControllerAnimated:YES];

Exécuter une seule animation. 

12

Vérifiez ceci pour Swift:

self.presentingViewController?.presentingViewController?.dismissViewControllerAnimated(true, completion: nil);
5
Victor Rius

Dans Swift 4

self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil); 

3
TheSwiftGuy77

J'ai lu tous les sujets et je n'ai pas trouvé de réponse appropriée. Si vous rejetez B, C disparaît immédiatement et crée un effet étrange. La manière appropriée est de présenter C en tant que contrôleur de vue enfant avec une animation personnalisée partant du bas, comme suit:

   [b addChildViewController:c];
    c.view.frame = CGRectOffset(b.view.bounds, 0, b.view.bounds.size.height);
    [b.view addSubview:c.view];
    [c didMoveToParentViewController:b];

    [UIView animateWithDuration:0.5 animations:^{
        c.view.frame = CGRectOffset(c.view.frame, 0, -b.view.bounds.size.height);
    } completion:^(BOOL finished) {

    }];

Et puis vous rejetez simplement B et tout semble beaucoup plus joli!

2
Rudolf J

Vous n'avez besoin que d'une commande de renvoi. Il suffit de rejeter B, puis C partira avec. 

2
Dancreek

Cela a fonctionné pour moi:

// Swift
presentingViewController?.dismissViewControllerAnimated(true, completion: nil)

// Objective-C
[self.presentingViewController dismissViewControllerAnimated:true completion:nil];
2
Nagra

Inspiré par la solution Albertos, j'ai créé une méthode de délégation en B avec un bloc pour afficher le résultat de la suppression d'un compte: 

#pragma - mark - AddAccountViewControllerDelegate Methods

- (void) dismissToSettings {
    [self dismissModalViewControllerAnimated:NO];
    [self dismissViewControllerAnimated:YES completion:^(void){[DKMessage showMessage:LS(@"Account was successfully created")];}];
}
0
wzbozon

Voici un moyen de rejeter plusieurs contrôleurs de vue modaux à l'aide d'un cycle de répétition:

Swift 3

// In this example code will go throw all presenting view controllers and 
// when finds it then dismisses all modals.
var splitViewController: UIViewController? = self

repeat {
    splitViewController = splitViewController?.presentingViewController
} while (!(splitViewController is UISplitViewController) && (splitViewController != nil))

splitViewController?.dismiss(animated: true, completion: nil)
0
Ramis

J'ai rencontré le même problème, et une meilleure solution créait un "DismissViewProtocol" comme suit:

Fichier: DismissViewProtocol.h

@protocol DismissViewProtocol <NSObject>
-(void)dismissView:(id)sender;
@end

Dans ma vue B-modal, répondons pour la méthode delegate:

dans mon fichier b.h:

#import "DismissViewProtocol.h"
@interface B-Modal : UIViewController <DismissViewProtocol>
...
@end

dans mon fichier b.m:

-(void) dismissView:(id)sender
{
 [((UIViewController *) sender) dismissModalViewControllerAnimated:NO];
 [self dismissModalViewControllerAnimated:YES];
}

Dans le même contrôleur de vue B, lorsque j'appelle le , Ensuite, dans ma vue modale B, lorsque j'appelle l'autre vue modale C, en supposant que pour segue:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    ((C-ViewController *)segue.destinationViewController).viewDelegate=self;
}

Enfin, dans mon fichier c.h, préparons le délégué:

@property(nonatomic, weak) id <DismissViewProtocol> viewDelegate;

Et dans mon fichier c.m, je viens de dire à mon viewDelegate de rejeter mon contrôleur de vue modal et lui-même:

-(void)closeBothViewControls
{
       [self.viewDelegate dismissView:self];
}

Et c'est tout.

J'espère que cela fonctionne pour vous tous.

0
Anibal Itriago

Le contrôleur de navigation a une propriété "viewControllers" qui est un tableau - vous pouvez le définir sur un nouveau tableau moins les deux contrôleurs de vue que vous souhaitez supprimer.