38 votes

Présenter un contrôleur de vue modale immédiatement après en avoir renvoyé un autre

Je suis licencier un modal-vue-contrôleur, puis immédiatement à la présentation d'un autre, mais ce dernier n'arrive jamais. Voici le code:

 [auto dismissModalViewControllerAnimated:YES];

 UIImagePickerController *sélecteur = [[UIImagePickerController alloc] init];
 sélecteur.delegate = self;
 sélecteur.sourceType = UIImagePickerControllerSourceTypesavedphotosalbum;
 [auto presentModalViewController:sélecteur de animated:YES];

La première modal VC glisse vers le bas, mais le nouveau picker ne vient jamais vers le haut. Aucune idée de ce qui se passe?

52voto

Prairiedogg Points 3594

Août 2012 Mise À Jour:

iOS 5 et plus ont introduit plus sûr Api pour faire des choses après les auxiliaires modaux ont animé dans / hors de l'endroit à l'aide de l'achèvement des blocs:

[self presentViewController:myModalVC animated:YES completion:^{}];
[self dismissViewControllerAnimated:YES completion:^{}];

Pré-Août 2012 Réponse:

J'ai rencontré un problème similaire lors du rejet de modal et de la présenter modal deux en succession rapide. Parfois modal deux spectacle après le modal a été rejeté, et parfois modal deux ne semble pas du tout et qui m'a rendu très triste.

Ressemble à une condition de course pour moi...

Mettre un+ 1 seconde de retard sur l'appelant de la méthode présentée modal deux, showModalTwo, fait modal deux apparaissent à chaque fois après le modal a été rejetée:

- (void)didDismissModalOne {
    [self performSelector:@selector(showModalTwo:) 
               withObject:someNumber 
               afterDelay:1.0f];
}

Cela a confirmé un soupçon qu'il y avait une sorte de course entre le licenciement de modal et de la présentation du modal deux. Mettre un délai sur l'appelant, toutefois, est inélégant et n'a pas de garantie que la condition de la course ne serait pas ré-apparaître dans d'autres circonstances.

Le problème

S'avère qu' UIViewControllers ont une propriété publique, modalViewController, qui est défini lors de l' presentModalViewController:animated: est appelé et démolie lors de l' dismissModalViewControllerAnimated: est appelé. Le hic, c'est qu'elle n'est pas déchirée vers le bas de manière synchrone, il est possible de créer une compétition entre la dépose de l'ancienne valeur de modalViewController et la création d'une nouvelle valeur de la manière suivante.

  1. Présent modal. myViewController.modalViewController maintenant des points de modal
  2. Rejeter modal. Processus d'arrière-plan pour abattre myViewController.modalViewController a commencé, mais myViewController.modalViewController encore des points de modal
  3. Présent modal deux, myViewController.modalViewController] maintenant les points à modale deux
  4. Système de rappel incendies, la création d' myViewController.modalViewController de nil, cela interrompt le processus de modal deux l'animation et le résultat est que l'utilisateur ne la voit jamais.

La course démarre à l'étape 2 et se manifeste à l'étape 4.

La solution

Ma solution a été de mettre un garde de la condition sur la méthode présentée modal deux pour s'assurer que myViewControoler.modalViewController a nil avant de tenter de présenter modal deux.

-(void)showModalTwo:(NSNumber *)aParameter {

    if (self.modalViewController) {        
            [self performSelector:@selector(showModalTwo:)
                       withObject:aParameter 
                       afterDelay:0.1f];
            return;
    }
    // You can now present the second modal safely.
}

A travaillé comme un charme. Une solution plus élégante peut inclure un délai d'attente.

Post script

Je n'ai vraiment pas comme les bureaux de l'aspect de cette solution. @Nemrod suggère, dans la accepté de répondre à cette question, que vous pouvez lancer la présentation du modal deux de l' viewDidDisappear: méthode de modal. J'ai bien aimé le son de cet événement approche axée sur, mais après avoir fait une mise en œuvre complète dans mon cas d'utilisation, je confirme que la condition de la course a persisté lors de la présentation de modal deux à l'aide d'un rappel à l'intérieur d' viewDidDisappear:. La seule façon d'être absolument certain que le modal deux sera présenté est de sondage à l'intérieur de la vue parent contrôleur jusqu'à ce que vous êtes absolument sûr qu' self.modalViewController est nil. Alors, et alors seulement est-il "bon" pop modal deux.

16voto

Nimrod Points 4472

Comme d'autres éléments animés, dismissModalViewControllerAnimated ne se bloque pas tant que le contrôleur de vue n'a pas disparu. Au lieu de cela, il "déclenche" le renvoi du contrôleur de vue. Vous devrez peut-être utiliser un rappel dans viewDidDisappear du contrôleur modal 1 qui appelle quelque chose comme modalViewControllerDisappeared dans le contrôleur de vue parent. Dans cette méthode, vous présentez le contrôleur modal 2. Sinon, ce que Robot K a dit.

14voto

Ilker Baltaci Points 3129
 [self dismissViewControllerAnimated:YES completion:^{
    //Present the new MVC 

}];
 

Remarque: Disponible iOS 5.0 et versions ultérieures.

5voto

Sid Points 6025
[self dismissModalViewControllerAnimated:NO];

 UIImagePickerController *picker = [[UIImagePickerController alloc] init];
 picker.delegate = self;
 picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
 [self presentModalViewController:picker animated:YES];

2voto

Kris Markel Points 8724

Ce qui se passe est que le point de vue du contrôleur supprime la référence à la modale de-vue-contrôleur une fois le rejeter animation est réalisée, ce qui arrive une fois que ce code est appelé, de sorte qu'il ne pense pas qu'il a un nouveau point de vue contrôleur de présenter modal.

Comment je fais avec, c'est de mettre un didDismissModalVC ivar d' YES après j'appelle dismissModalViewController. Puis, dans ma viewDidAppear: méthode, j'ai vérifier la valeur de la ivar et présente ensuite le nouveau modal-vue-contrôleur. (Se souvenir de définir la valeur de retour d' NO donc je n'ai pas coincé éternellement rejetant modal vue des contrôleurs.)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X