TabBarApplication : changer de selectedViewController

bnkbnk Membre
mai 2009 modifié dans API UIKit #1
Bonjour,

Mon projet se termine, je navigue de vues en vues à  l'aide d'une tabbar.
Chaque sections de ma tabBar est en fait chargée à  partir d'un .xib qui contient une vue qui est elle même controllée par un UIViewController propre.

Je souhaite créer un menu un peu comme celui qui se crée automatiquement (more ...) lorsqu'on ajoute plus de 5 items à  notre tabBar:

f8b05fc285c6b1e3253fe3af26742.png

A la différence que le miens ne doit pas être une gridView car je ne veux pas une nouvelle barre en haut de mon écran qui va me bouffer de la place uniquement pour revenir en arrière.

Il faudrait que je puisse afficher mes items Quizz, Pendu et Liste dans une view Activité comme ca:
85aced4d8dfd00b476007805d1706.png

Ici la navigation se fait simplement en cliquant un bouton.
Si on clique sur le bouton Quizz, on remplace la vue du menu Activités par la vue du Quizz et si on veut faire un Pendu on clique sur un bouton retour en haut de ma vue quizz pour remplacer cette dernière par la vue de menu des Activités et permettre à  l'utilisateur de repartir vers la vue du Pendu.

C'est donc une sorte de double navigation.
Comment faire pour changer de UIView et de UIViewController lorsque l'utilisateur clique sur un bouton de ma vue Activité?

J'imagine qu'il faut agir du coté de mon tabBarController en lui passant par exemple tabBarController.selectedViewController = quizzViewController mais je ne sais pas comment y accèder à  partir de mon activiteController.

Merci,

Réponses

  • bnkbnk Membre
    mai 2009 modifié #2
    Je pense avoir trouvé une solution en changeant la liste des controllers de mon tabBar comme ceci à  chaque fois qu'on press un boutton.

    <br />[self.tabBarController setViewControllers:monNouveauTableaudeControllers];<br />
    


    Il faut donc que je prépare 4 tableaux de controllers différents pour chaque cas de figure:
    - Activité
    - Quizz
    - Pendu
    - Draglist

    Le tableau de controllers par défaut étant celui de "Activité", je changerai par celui de Quizz si on press le bouton Quizz comme ça on retrouvera à  la place de la section Activité une section Quizz (ndlr: la section étant un élément du tabbar, sur mon dernier screenshot, on a section : Expert, Fiches, Activités, Quizz, More).

    Voici comment je procède:
    -> j'ajoute toute les sections possibles à  ma tabBarApplication via InterfaceBuilder.
    -> je copie le self.tabBarController.viewControllers (comprenant toutes les sections) dans un nouveau tableau: copyViewControllers
    -> je crée un customViewControllers avec les sections par défaut (Expert, Fiches, Activités, Application, Forum) en retirant les viewControllers que je ne souhaite pas afficher.

    Tout fonctionne comme je le veux jusque ici, voici le code:
    <br />//<br />//  PolytechnicumAppDelegate.m<br />//<br />#import &quot;PolytechnicumAppDelegate.h&quot;<br /><br />@implementation PolytechnicumAppDelegate<br /><br />@synthesize window;<br />@synthesize tabBarController;<br />@synthesize copyViewControllers;<br /><br />/////////////////////////////////////////<br />// GESTION APPLICATION       &nbsp; //<br />/////////////////////////////////////////<br /><br />- (void)applicationDidFinishLaunching:(UIApplication *)application {<br />	<br />    // Add the tab bar controller&#39;s current view as a subview of the window<br />    [window addSubview:tabBarController.view];<br />	<br />	copyViewControllers = [NSMutableArray arrayWithArray:self.tabBarController.viewControllers];<br />	<br />	NSMutableArray *customViewControllers = [NSMutableArray arrayWithArray:copyViewControllers];<br />	[customViewControllers removeObjectAtIndex:5];<br />	[customViewControllers removeObjectAtIndex:5];<br />	[customViewControllers removeObjectAtIndex:5];<br />	[self.tabBarController setViewControllers:customViewControllers];<br />}<br /><br />- (void)dealloc {<br />    [tabBarController release];<br />    [window release];<br />    [super dealloc];<br />}<br /><br />@end<br />
    



    Voici ce que j'obtiens donc:

    01a62785fd06601e3b5b7c2319095.png

    Maintenant je vais créer 3 autres "customViewControllers", un pour Quizz, un pour Pendu et un pour dragList histoire de remplacer le tableau de controllers par celui qui contient les sections que je veux en fonction du choix de l'utilisateur dans "Activités" avec la méthode:
    [self.tabBarController setViewControllers:monNouveauTableaudeControllers];

    C'est ici que les choses se compliquent car je le fait dans une classe externe, celle du controller de "Activité" et je n'arrive pas à  récupérer mon "copyViewControllers" que j'ai déclaré dans la classe : "PolytechnicumAppDelegate".

    Voici mon code pour le controller Activité:
    <br />#import &quot;ActiviteController.h&quot;<br />#import &quot;PolytechnicumAppDelegate.h&quot;<br /><br />@implementation ActiviteController<br />@synthesize customQuizzViewControllers;<br /><br />- (void)viewDidLoad {<br />    [super viewDidLoad];<br />	PolytechnicumAppDelegate *accessPoly = [[PolytechnicumAppDelegate alloc] init];<br />	NSLog(@&quot;copyViewControllers: %@&quot;, accessPoly-&gt;copyViewControllers);<br />	<br />		//quizz<br />	/*customQuizzViewControllers = [NSMutableArray arrayWithArray:copyViewControllers];<br />	[customQuizzViewControllers exchangeObjectAtIndex:5 withObjectAtIndex:2]<br />	[customQuizzViewControllers removeObjectAtIndex:5];<br />	[customQuizzViewControllers removeObjectAtIndex:5];<br />	[customQuizzViewControllers removeObjectAtIndex:5];<br />	 */<br />		//pendu<br />	<br />		//draglist<br />}<br /><br />- (IBAction)lanceDraglist:(id)sender {<br />	// [self.tabBarController setViewControllers:customDraglistViewControllers];<br />}<br /><br />- (IBAction)lancePendu:(id)sender {<br />	//[self.tabBarController setViewControllers:customPenduViewControllers];<br />}<br /><br />- (IBAction)lanceQuizz:(id)sender {<br />	[self.tabBarController setViewControllers:customQuizzViewControllers];<br />}<br />@end<br />
    


    Le NSLog retourne (null), pourquoi?
    Pensez-vous que ma solution soit correcte?

    J'ai essayé de chercher par moi même mais là  je ne sais vraiment pas si c'est la bonne solution, toute aide est vraiment la bien venue, d'avance, merci ;)
  • bnkbnk Membre
    mai 2009 modifié #3
    Bonjour,

    Je continue mes péripéties seul, on verra si quelqu'un peut venir me conseiller... :p

    Afin de simplifier le code et les explications j'ai tout regroupé dans la même classe (celle de mon Application).

    Voici donc comment je procède, ici vous comprendrez rapidement mon raisonnement:

    <br />//<br />//  PolytechnicumAppDelegate.m<br />//  Polytechnicum<br />//<br />//  Created by Pierre on 17/02/09.<br />//  Copyright __MyCompanyName__ 2009. All rights reserved.<br />//<br /><br />#import &quot;PolytechnicumAppDelegate.h&quot;<br /><br />@implementation PolytechnicumAppDelegate<br /><br />@synthesize window;<br />@synthesize tabBarController;<br />@synthesize copyViewControllers, customViewControllers, customQuizzViewControllers, customPenduViewControllers, customDraglistViewControllers;<br /><br />/////////////////////////////////////////<br />// GESTION APPLICATION INGENIUM        //<br />/////////////////////////////////////////<br /><br />- (void)applicationDidFinishLaunching:(UIApplication *)application {<br />	<br />    // Add the tab bar controller&#39;s current view as a subview of the window<br />    [window addSubview:tabBarController.view];<br />	<br />	copyViewControllers = [NSMutableArray arrayWithArray:self.tabBarController.viewControllers];<br />	<br />	customViewControllers = [NSMutableArray arrayWithArray:copyViewControllers];<br />	[customViewControllers removeObjectAtIndex:5];<br />	[customViewControllers removeObjectAtIndex:5];<br />	[customViewControllers removeObjectAtIndex:5];<br />	<br />	customQuizzViewControllers = [NSMutableArray arrayWithArray:copyViewControllers];<br />	[customQuizzViewControllers exchangeObjectAtIndex:2 withObjectAtIndex:5];<br />	[customQuizzViewControllers removeObjectAtIndex:5];<br />	[customQuizzViewControllers removeObjectAtIndex:5];<br />	[customQuizzViewControllers removeObjectAtIndex:5];<br />	<br />	customPenduViewControllers = [NSMutableArray arrayWithArray:copyViewControllers];<br />	[customPenduViewControllers exchangeObjectAtIndex:2 withObjectAtIndex:6];<br />	[customPenduViewControllers removeObjectAtIndex:5];<br />	[customPenduViewControllers removeObjectAtIndex:5];<br />	[customPenduViewControllers removeObjectAtIndex:5];<br />	<br />	customDraglistViewControllers = [NSMutableArray arrayWithArray:copyViewControllers];<br />	[customDraglistViewControllers exchangeObjectAtIndex:2 withObjectAtIndex:7];<br />	[customDraglistViewControllers removeObjectAtIndex:5];<br />	[customDraglistViewControllers removeObjectAtIndex:5];<br />	[customDraglistViewControllers removeObjectAtIndex:5];<br />	<br />	//Affichage de la list de controlleurs initiale<br />	[self displaycustomViewControllers];<br />	//[self displaycustomQuizzViewControllers];<br />	//[self displaycustomPenduViewControllers];<br />	//[self displaycustomDraglistViewControllers];<br />	<br />	//animation permettant d&#39;afficher plus longtemps le Default.png<br />	imagePresentation = [[[UIImageView alloc] autorelease] initWithImage:[UIImage imageNamed:@&quot;Default.png&quot;]];<br />	[tabBarController.view addSubview:imagePresentation];<br />    [UIView beginAnimations:@&quot;ImagePresentation&quot; context:nil];<br />    [UIView setAnimationBeginsFromCurrentState:YES];<br />    [UIView setAnimationDelegate:self];<br />    [UIView setAnimationDidStopSelector:@selector( removeDefaultView: )];<br />    [UIView setAnimationDelay:1.0];<br />    [UIView setAnimationDuration:1];<br />    [imagePresentation setAlpha:0.0];<br />    [UIView commitAnimations];<br />	<br />	NSTimer *timer;<br />	<br />	timer = [NSTimer scheduledTimerWithTimeInterval: 10<br />											 target: self<br />										 &nbsp; selector: @selector(waitToChangeControllers:)<br />										 &nbsp; userInfo: nil<br />											repeats: NO];<br />}<br />- (void) waitToChangeControllers: (NSTimer *) timer<br />{<br />    [self displaycustomQuizzViewControllers];<br />}<br /><br />/////////////////////////////////////////<br />// GESTION ViewControllers tabBar      //<br />/////////////////////////////////////////<br /><br />- (void) displaycustomViewControllers{<br />	[self.tabBarController setViewControllers:customViewControllers];<br />}<br /><br />- (void) displaycustomQuizzViewControllers{<br />	printf(&quot;On change le tableau de controllers&quot;);<br />	[self.tabBarController setViewControllers:customQuizzViewControllers];<br />}<br /><br />- (void) displaycustomPenduViewControllers{<br />	[self.tabBarController setViewControllers:customPenduViewControllers];<br />}<br /><br />- (void) displaycustomDraglistViewControllers{<br />	[self.tabBarController setViewControllers:customDraglistViewControllers];<br />}<br /><br />- (void) removeDefaultView<br />{<br />    [imagePresentation removeFromSuperview];<br />}<br /><br /><br />/*<br /> // Optional UITabBarControllerDelegate method<br /> - (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {<br /> }<br /> */<br /><br />/*<br /> // Optional UITabBarControllerDelegate method<br /> - (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed {<br /> }<br /> */<br /><br /><br />- (void)dealloc {<br />	//[copyViewControllers release];<br />	[imagePresentation release];<br />    [tabBarController release];<br />    [window release];<br />    [super dealloc];<br />}<br /><br />@end<br /><br />
    


    Je suis sur la bonne voie car lorsque je charge mon application au démarrage si je sélectionne un de ces tableaux de controllers pour mon tabBar j'obtiens exactement ce qu'il faut!

    Screenshot d'exemple si je décommente comme ceci:

    <br />	//[self displaycustomViewControllers];<br />	[self displaycustomQuizzViewControllers];<br />	//[self displaycustomPenduViewControllers];<br />	//[self displaycustomDraglistViewControllers];<br />
    


    37e0d007031e487c6754983515851.png

    J'ai mis un timer pour voir si je pouvais changer dynamiquement le tableau de controllers mais mon application crash. Une idée?
  • allianallian Membre
    23:15 modifié #4
    J'ai lu assez vite ton post, mais si j'ai bien compris tu veu qu'au clic d'une image un nouveau controller s'affiche.

    Si tu veu que cela slide utilise le navigationController de ton controlleur principal, sinon tu removeFromSuperview le controlleur qui affiche toutes tes images et tu addSubview avec le controlleur choisi.

    C'est juste une piste.
  • bnkbnk Membre
    mai 2009 modifié #5
    Oui, c'est ça allian!

    Je me suis peut être bien compliqué la tâche, le truc c'est que je ne vois pas comment déclarer un nouveau contrôleur de Quizz par exemple pour le balancer à  la place de celui de mes images (activiteController) en utilisant addSubview et removeFromSuperView.

    Car je n'ai pas de NavigationController vu que je ne suis pas dans un GridView (enfin jme plante peut être...).
    Voici ce que donne mon MainWindow.xib:
    2752926b550eada05b8dca8ac5a3d.png

    Enfin je vais chercher de ce coté car j'étais partit dans une autre direction, merci pour la réponse je commençait à  désespérer  :)
  • bnkbnk Membre
    23:15 modifié #6
    Je ne trouve pas mon NavigationController principal (surement parce que je n'en ai pas?..) et je ne souhaite pas en ajouter à  mon .xib Activité car ça ajoute une topBar qui bouffe de la place sur l'écran et j'en manque cruellement.


    Il semble que :
    [self.tabBarController setViewControllers:customQuizzViewControllers animated:YES];
    


    Soit plus adapté à  ce que je recherche, sauf que quand je change "dynamiquement" ceci ça crash alors qu'au lancement de l'application si je change custromQuizzViewControllers par un autre j'obtiens bien la liste des controllers que je veux pour mon tabBar.

    Comment le faire dynamiquement sans que l'appli crash? Peux être faut-il refresh quelque chose quelque part...?

    Un log du crash:
    <br />GNU gdb 6.3.50-20050815 (Apple version gdb-962) (Sat Jul 26 08:14:40 UTC 2008)<br />Copyright 2004 Free Software Foundation, Inc.<br />GDB is free software, covered by the GNU General Public License, and you are<br />welcome to change it and/or distribute copies of it under certain conditions.<br />Type &quot;show copying&quot; to see the conditions.<br />There is absolutely no warranty for GDB.&nbsp; Type &quot;show warranty&quot; for details.<br />This GDB was configured as &quot;i386-apple-darwin&quot;.<br />warning: Unable to read symbols for &quot;/System/Library/Frameworks/UIKit.framework/UIKit&quot; (file not found).<br />warning: Unable to read symbols from &quot;UIKit&quot; (not yet mapped into memory).<br />warning: Unable to read symbols for &quot;/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics&quot; (file not found).<br />warning: Unable to read symbols from &quot;CoreGraphics&quot; (not yet mapped into memory).<br />warning: Unable to read symbols for &quot;/System/Library/Frameworks/MediaPlayer.framework/MediaPlayer&quot; (file not found).<br />warning: Unable to read symbols from &quot;MediaPlayer&quot; (not yet mapped into memory).<br />Program loaded.<br />sharedlibrary apply-load-rules all<br />Attaching to program: `/Users/pierre/Library/Application Support/iPhone Simulator/User/Applications/0BCB05AD-2907-47C8-9659-9BAEAEAA5212/Polytechnicum.app/Polytechnicum&#39;, process 25003.<br />(gdb)
    

  • allianallian Membre
    23:15 modifié #7
    Pour faire cela il y a plusieurs solutions. J'ai eut le même problème dans une appli regarde ici : http://www.osx-dev.com/index.php?topic=3525.0

    Pour résoudre cela tu peu comme dis dans le post, créer un singleton de ton navigationController principal, soit y accéder par ton appDelegate meme si c'est déconseillé ou alors comme moi j'ai fait créer une propriété qui t'y permet d'accéder comme le NSIndexPath.

  • bnkbnk Membre
    23:15 modifié #8
    J'ai lu ton post, j'ai appris des choses :)

    Par contre je viens de résoudre mon problème autrement et simplement (car mon code était bon en fait!) enfin.. il y avait une erreur au niveau de la copie de mon MutableArray.

    C'est comme ca qu'il faut faire:

    copyViewControllers = [self.tabBarController.viewControllers mutableCopy];
    


    Merci pour tes réponses, je m'empresse de boucler mon projet (il n'est pas exclu que j'ai de nouveau besoin d'aide d'ici là  ) :)
  • bnkbnk Membre
    mai 2009 modifié #9
    Projet terminé ;)
    Merci en particulier à  Philippe49 et AliGator qui ont passé pas mal de temps à  bien m'expliquer.
    ps: il y a de fortes chances pour que je continue à  trainer dans le coin pour améliorer tout ça et faire de nouvelles choses.
  • muqaddarmuqaddar Administrateur
    23:15 modifié #10
    dans 1243554126:

    Projet terminé ;)
    Merci en particulier à  Philippe49 et AliGator qui ont passé pas mal de temps à  bien m'expliquer.
    ps: il y a de fortes chances pour que je continue à  trainer dans le coin pour améliorer tout ça et faire de nouvelles choses.



    Ajoute le dans les projets finis quand Apple l'aura validé. ;)
  • allianallian Membre
    23:15 modifié #11
    Cool pour toi.
Connectez-vous ou Inscrivez-vous pour répondre.