Accueil > Uncategorized > ModalView en cascade …

ModalView en cascade …

Voici une petite astuce qui vous évitera quelques heures de prise de tête. Imaginons une application qui permet à un utilisateur d’ouvrir une vue modale (invoquée grâce au message « presentModalViewController » de la classe UIViewController). Jusqu’ici tout va bien. Là où cela se complique c’est quand cette même vue modale appelle une deuxième vue modale, en cascade donc. Le problème se pose au moment ou l’on veut tout simplement refermer toutes ces vues et revenir à la vue initiale tout au début de la pile.

Nous avons donc : ViewControllerA qui invoque la vue modale B en lui associant le ViewController B.

ViewControllerB invoque à son tour la vue modale C en lui associant le ViewControllerC.

On peut par exemple rencontrer ce genre d’architecture dans une application qui doit envoyer par mail, les différents champs d’une tableView. Le ViewController de la tableView est donc le controller A.

Celui ci appelle une modalView B qui va permettre à l’utilisateur de séléctionner les champs qui vont être inclus dans le mail. Le controller de cette vue (instanciée par le controller A) s’appelle donc ViewControllerB. Enfin une fois que l’utilisateur a sélectionné les champs dans la vue B, le controller B invoque la vue C qui est aussi une vue modale s’occupant de l’envoi à proprement parlé du mail. Son controller appelé ViewControllerC est donc une instance de la classe MFMailComposeViewController (dispo à partir de l’os 3.0 si je ne m’abuse).

Tout va bien me direz vous. Sauf qu’une fois que le mail est envoyé tout se complique. En effet la méthode « didFinishWithResult » qui est appelée par le composant mail de « MFMailComposeViewController »  doit être définie dans le ControllerB. Et lorsque dans cette même méthode vous invoquez « dismissModalViewControllerAnimated » seule la vue C disparait. L’utilisateur revient alors sur la vue B alors qu’il aurait du naturellement revenir sur la vue A étant donné que tout le processus d’envoi de mail est terminé. Un deuxième dismiss dans la foulée ne change rien au problème et la vueB continue d’occuper le premier plan de l’application.

Après avoir fait un grand tour des forums et des sites qui parlent du problème, j’ai trouvé une solution simple me semble t-il et qui marche très bien pour ce cas précis. Le controller responsable d’une vue modale est le controller parent. Cela veut clairement dire (et la doc d’Apple le précise) que c’est le controller parent qui doit faire le « present » et le « dismiss ». Or dans beaucoup de cas y compris celui de notre exemple, le controller B se contente d’appeler le dismiss sur lui même sachant qu’il sera routé vers son parent. vous me suivez ? Ma solution consiste alors à ne pas envoyer le message dismiss sur le controllerB (en éspérant qu’il le re-route) mais bel et bien sur le controllerA.

Pour se faire rien de plus simple :

Code du Controller A :

//allocation de la mémoire et création d’une instance du controllerB

ControllerB *monControllerB = [[ControllerB alloc] initWithNibName:@ »ControllerB » bundle:nil];

//On précise au controller B via une variable membre quel est son Controller parent (ici le Controller A)

monControllerB.parentViewController = self;

//Invocation de la vue B

[self presentModalViewController:monControllerB animated:YES];

Code du Controller B :

function didChooseRowsToSend

//allocation de la mémoire et création d’un composer

MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];

//Affectation du delegate de notre composer (celui qui va gérer les affaire pour le composer est le Controller B)

mc.mailComposeDelegate = self;

//invocation de la vue C qui est la vue du mail à envoyer

[self presentModalViewController:mc animated:YES];

fin de fonction

et enfin le plus important :

fonction didFinishWithResult du Controller B :

//Envoi du dismiss au Controller stockée dans la variable membre qui n’est autre que le Controller A

[self.parentViewController dismissModalViewControllerAnimated:YES];

Ceci aura pour simple effet de fermer toutes les vue modales qui déscendent du Controller A à savoir le Controller B et C

Catégories :Uncategorized Étiquettes : , , , ,
  1. Aucun commentaire pour l’instant.
  1. No trackbacks yet.

Laisser un commentaire