UISplitView et vue d'authentification/menu

Bonjour à  tous,



Après avoir longuement cherché sur la toile une solution à  mon problème j'en suis arrivé à  la conclusion qu'il faut que je me résolve à  arranger mon application afin que celle ci soit techniquement réalisable via xCode 4.5 (application pour un IPad).



Le principe est simple, j'aimerais lors de l'ouverture de mon application une vue gérant l'authentification que j'ai déjà  créer, une fois loger l'utilisateur se retrouve sur une vue proposant un menu type iCarrousel ou simples boutons n'importe. Ces vue existe déjà  et sont déjà  implémentées.

Cependant, lors de la sélection d'un menu je souhaiterais arrivé sur un splitView ... Pour prendre un exemple type, au niveau du menu j'ai client et article. Lors de la sélection de client il faudrait arrivé sur un split view implémentant une liste de client dans le master et la fiche client dans la detailview. Cela ca de même pour les articles.

Sur le coup je me suis dit que je pouvais utiliser le même splitview et ne changer que la gestion des données derrière en fonction du menu sélectionné.

Jusque la pas de problème. J'ai fait mes tests les 2 systèmes de vues fonctionnes l'une comme l'autre séparément.



Je décide donc de créer un nouveau projet avec pour template le master détail view que je ne touche pas pour le moment (donc gestion de l'ajout de la date avec affichage de cette date par défaut). J'ajout 2 vues pour l'authentification et le menu. Je place un bouton sur chaque permettant de simuler le login du user sur la première et la sélection du menu sur l'autre.

Ainsi je devrais me retrouver avec ceci :

LoginView ---ModalTransition---> MenuView ---ModalTransition---> DefaultSplitView



Je me heurte donc à  plusieurs erreurs.

Déjà  le splitView étant implémenter dans l'appDelegate cela ne pouvais que crasher car ma première vue est gérer par un viewController classique.

Je me renseigne donc ... forums, documentation Apple, etc ...

Je découvre petit à  petit que finalement le splitView doit être le rootViewController dans le launching de l'application :


A split view controller must always be the root of any interface you create. In other words, you must always install the view from aUISplitViewController object as the root view of your application's window. The panes of your split view interface may then contain navigation controllers, tab bar controllers, or any other type of view controller you need to implement your interface. Split view controllers cannot be presented modally.




[font="Lucida Grande, Geneva, Helvetica, Arial, sans-serif"]Je continue donc à  chercher afin de trouver une solution intermédiaire. Je tombe sur un projet de Mat Gommel avec son MGSplitView mais je souhaiterais rester dans les cordes de ce que propose xCode. J'ai également réussi à  implémenter une vue (modale) qui s'affiche juste après le chargement de la détailView du split cachant ainsi le splitview. Je fait donc disparaà®tre cette vue une fois le menu sélectionné comme ceci:[/font]



[font="Lucida Grande, Geneva, Helvetica, Arial, sans-serif"]chargement de la vue d'authentification dans la sub configureView du viewDidLoad du DetailViewController du splitView :
[/size][/font]<br />
[font="Lucida Grande, Geneva, Helvetica, Arial, sans-serif"][size="2"][self performSegueWithIdentifier:@&quot;goLog&quot; sender:self];[/size][/font]<br />
[font="Lucida Grande, Geneva, Helvetica, Arial, sans-serif"][size="2"]
[/font]

[font="Lucida Grande, Geneva, Helvetica, Arial, sans-serif"]Puis lors de la sélection du menu : [/font]
<br />
[font="Lucida Grande, Geneva, Helvetica, Arial, sans-serif"][size="2"][self dismissViewControllerAnimated:YES completion:nil];<br />
[/size][/font]



[font="Lucida Grande, Geneva, Helvetica, Arial, sans-serif"]Ce qui m'affiche un message d'erreur, non rédhibitoire puisque pas de crash mais message d'erreur quand même, à  chaque affichage de la vue de login : [/font]


Unbalanced calls to begin/end appearance transitions for <UISplitViewController : 0x1fd56f60>.




Par conséquent j'aurais besoin d'avis éclairé sur la question car il est fort probable que je manque cruellement d'explication théorique sur le fonctionnement de vues séparées ...

Est ce qu'il y a une autre solution pour utiliser le splitView avec authentification et menu ? Est ce que le fait d'utiliser des vues modales comme expliqué ci dessus est correct techniquement parlant ?

Je me dit que c'est tout de même possible car c'est le principe de fonctionnement de l'application "Mes amis" !



Ayant contacté un technicien d'Appel voici sa réponse :
[font=arial, sans-serif]Segueing to a Split View Controller is unsupported. As per the "View Controller Catalog" guide:[/font]

[font=arial, sans-serif]"A split view controller must always be the root of any interface you create. In other words, you must always install the view from a UISplitViewController object as the root view of your application's window". You should re-work your interface to either move the UISplitViewController to the root of your UI or avoid using UISplitViewController. One way to implement the former option is to present the authentication and menu modally when the app is first launched. Once the user has provided the appropriate information, you can dismiss the modal view controller to reveal the split view controller.[/font]



Merci d'avoir pris le temps de me lire image/thumbsup.gif' class='bbc_emoticon' alt=' :D ' />
«1

Réponses

  • CéroceCéroce Membre, Modérateur
    Je pense que tu as bien cerné les deux approches:

    1) mettre UISplitViewController en root de la fenêtre et donc, afficher l'écran de login et le carrousel dans un VC modal.

    2) se passer de UISplitViewController.



    UISplitViewController n'est pas une classe très réussie. Notamment, sa gestion des UIBarButonItems lors de l'affichage/masquage du panneau latéral m'a posé de nombreux problèmes. Je serais donc d'avis d'utiliser le code de Mattt Gemmel, qui est une sommité dans notre microcosme.

    Par ailleurs, si l'appli ne fonctionne qu'en orientation horizontale, implémenter ce mécanisme toi-même n'est pas sorcier.
  • [font=helvetica, arial, sans-serif]Il est vrai que les possibilité offert par le projet de Matt Gemmel est intéressant (beaucoup plus de flexibilité). Cependant je n'est jamais travailler des point .xib car j'ai commencé la programmation ios au mois de septembre/octobre donc directement avec un storyboard. Par contre j'ai déjà  vu énormément de tuto avec les fichier .xib et j'ai pour un UITableview créé une cellule en .xib avec un controller spécifique afin de la customisé. Mais dans tout les cas la trame est fixer par le storyboard. En utilisant le code de Matt Gemmel la base du projet est donc en .xib ou alors je peut créer un projet storyboard et insérer les éléments du MGSplitView petit à  petit en fonction des besoins ?[/font]
  • CéroceCéroce Membre, Modérateur
    Là , je dois dire que je n'en sais trop rien. Effectivement, je ne suis pas sûr qu'on puisse choisir les deux view controllers utilisés par la MGSplitView dans le Storyboard. À part essayer (le résultat m'intéresse ;-) ), je n'ai pas de solution.
  • LarmeLarme Membre
    décembre 2012 modifié #5
    Une petite présentation sinon ?



    Au passage, je salue l'effort de recherche de d'argumentation (j'avoue n'avoir que survolé) pour un premier post sur le forum, c'est rare.
  • Voila présentation, certes succincte, mais effectuée image/wink.png' class='bbc_emoticon' alt=';)' />



    Alors voila après quelques tests j'ai mis la (demi) solution suivante en place (avec storyboard) :
    1. Création d'un projet en master détails pour récupérer le template fonctionnel du splitView.
    2. ajout d'un viewController avec image, textFields, button et tout ce qui va bien pour le login d'un user
    3. Je relie le détailview avec un modal segue et lui donne un nom
    4. Je relier un bouton de déconnexion présent dans un masterview toujours en modal et toujours en lui attribuant un petit nom.
    5. après l'appel du configureView du detailView je lance un prepareForSegue pour afficher ma vue d'authentification via le modal segue
    6. puis il suffit de dismiss la vue d'authentification une fois le login/mdp validé
    7. navigation avec tabbar dans le masterview
    8. lors de la déconnexion même principe (affichage vue modale)


    L'inconvénient est que c'est une vue modale, donc lors de la déconnexion et d'une reconnexion avec un login différent, et bien on atterris à  la ou le dernier utilisateur s'est déconnecté. Par conséquent cela va provoquer quelques problèmes de droits ...

    L'idéal serais un push segue lors de la déconnexion seulement on en revient au problème du splitView qui ne supporte pas une navigation qui n'est pas inhérente à  son fonctionnement.



    Il faudrait peut-être effectué un refresh complet splitView lors d'une connexion ==> je teste ca demain.

    ou alors peut-etre qu'il est possible de faire un replace au lieu d'un appel modal de la vue afin de l'afficher dans le detail view. Il suffirait après de "bloquer" temporairement l'accès à  la master view en la désactivant ou en la cachant. C'est prévu dans le splitViewcontroller ? ==> je vais tester ca demain également.



    Sinon j'avais également réussi en insérant une vue d'authentification créer dans un fichier .xib et qui était appelé et détruite dans l'appDelegate.



    Dans les 2 cas on se retrouve avec se problème d'initialisation du split lors de la déconnexion / reconnexion.



    Personnellement j'ai l'impression que cette "technique" avec une vue modale est un peu barbare mais je me dit que ca doit être courant dans les applications ipad qui utilise le splitView ... On peut prendre l'exemple de l'application (native ?) "Mes amis" qui effectue une authentification avant d'afficher des vues séparées ...



    Je vous tiens au courant de l'avancé, mais si vous avez des infos concernant mes interrogations précédentes je suis preneur de toutes informations image/wink.png' class='bbc_emoticon' alt=';)' />
  • AliGatorAliGator Membre, Modérateur
    décembre 2012 modifié #7
    Sans rapport avec la question mais juste pour dire que je seconde Larme et te félicite de ta démarche, a savoir chercher par toi-même et nous indiquer dans tes posts ce que tu as essayé, lu, testé, et tes conclusions, ainsi que la démarche de nous tenir au courant.



    ça a l'air de rien mais beaucoup de nouveaux sur les forums viennent le bec ouvert sans chercher ou expliquer ce qu'ils ont testé et en espérant en réponse la solution avec le code tout cru, au lieu de commencer par chercher eux-même, expliquer leur démarche, etc.



    Ce n'est pas ton cas au contraire et c'est assez rare pour être signalé, et on dit toujours quand ça va pas jamais quand ça va bien, donc cette fois je le dit, merci, c'est apprécié ;-)
  • klozenklozen Membre
    décembre 2012 modifié #8
    'Larme' a écrit:


    Au passage, je salue l'effort de recherche de d'argumentation (j'avoue n'avoir que survolé) pour un premier post sur le forum, c'est rare.



    'AliGator' a écrit:


    Sans rapport avec la question mais juste pour dire que je seconde Larme et te félicite de ta démarche, a savoir chercher par toi-même et nous indiquer dans tes posts ce que tu as essayé, lu, testé, et tes conclusions, ainsi que la démarche de nous tenir au courant.



    ça a l'air de rien mais beaucoup de nouveaux sur les forums viennent le bec ouvert sans chercher ou expliquer ce qu'ils ont testé et en espérant en réponse la solution avec le code tout cru, au lieu de commencer par chercher eux-même, expliquer leur démarche, etc.



    Ce n'est pas ton cas au contraire et c'est assez rare pour être signalé, et on dit toujours quand ça va pas jamais quand ça va bien, donc cette fois je le dit, merci, c'est apprécié ;-)




    Pas de problème c'est normal image/wink.png' class='bbc_emoticon' alt=';)' />

    Je vois trop de forums avec des topics vide de sens par le fait que le créateur demande du code comme tu le dit si bien image/wink.png' class='bbc_emoticon' alt=';)' /> , ou alors que les réponses s'apparentent à  des citations de doc alors que la plus part du temps il est recherché une explication autre que la doc officielle car justement la doc officielle n'a pas été comprise...

    Du coup je me dit qu'une explication maison en français sur mon problème ça peut pas faire de mal surtout que les explications à  se sujet sont souvent en anglais ...



    Par ailleurs je vous joins 2 projet et leur code source respectif.

    Le fichier SplitViewControllerWithLogin contient un projet brut envoyé par un technicien d'Apple pour appuyé son explication sur le principe de la vue modal qui cache le splitView. Le code est donc plus clair avec plus de commentaire. C'est une très bonne base je trouve à  une exception près (et oui il y a toujours un "mais" image/wink.png' class='bbc_emoticon' alt=';)' /> )



    Et oui car qui dit Login dit déconnexion puis (re)login ! Du coup je m'atèle et en partant du code source reçu je monte un projet vite fait avec un masterView modifier (tabbar) et du coup un bouton déconnexion (vous trouverez ca dans le fichier Split_V8)
    V8 ne signifiant pas un moteur automobile mais une version subodorant des version Vx.x d'essai ... image/crazy.gif' class='bbc_emoticon' alt=' B) ' />




    bref le login est fonctionnel, la navigation aussi : affichage/ajout/modification de l'heure avec le template de base puis ajout d'un tabbar dans la masterView pour gérer une autre liste de donnée sur laquelle il y a une cellule (en dur pour le test bien entendu) qui affiche également un texte dans la vue détail du splitView. Cette masterView posséde également un bouton déconnexion qui finalement ne fait qu'afficher la vue login. Qui elle à  son tour se dismiss lors du login.



    Le problème est celui évoqué dans le post précédent. Donc je me remet au boulot et vous tiens au courant image/wink.png' class='bbc_emoticon' alt=';)' />



    Excepté ce problème les versions jointes devrait être fonctionnelle image/clap.gif' class='bbc_emoticon' alt=' :D ' />
  • Oyé oyé voila après une batterie de tests et des heures d'acharnement j'ai réussi à  obtenir ce que je voulais. Je vous expliquerais ca dans un post plus détaillé avec des exemples etc.



    Pour l'heure j'ai une quesiton à  propos de ce storyboard :

    <br />
    -(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item{<br />
    NSLog(@&quot;%@&quot;,item);<br />
    }<br />
    




    Cela afin de vérifier le changement d'onglet et c'est le drame !! image/crybaby.gif' class='bbc_emoticon' alt=' :'( ' />



    Je m'aperçoit que la sub n'est même pas appelé. Bon direct je vais vérifier mon .h et je vais ajouter dans l'interface : (j'ai tellement de fois oublié d'ajouter ces delegate que maintenant dès que j'ai un problème de sub qui n'est pas appelé que je regarde ca direct)
    <br />
    @interface MasterViewController : UITableViewController &lt; UITabBarDelegate, UITabBarControllerDelegate&gt;<br />
    




    Cependant cela n'y change rien du tout image/crybaby.gif' class='bbc_emoticon' alt=' :'( ' /> image/crybaby.gif' class='bbc_emoticon' alt=' :'( ' />



    Bon du coup je me dit que j'ai du mal initialiser quelque chose. Je fait des modif dans le storyboard au niveau des segue, je met un navigationController unique suivis du tabbar mais rien n'y fait.



    Du coup j'essaye ca :
    self.navigationController.tabBarItem.title = @&quot;lib onglet&quot;;<br />
    
    placé dans le viewDidLoad de la masterView.



    Et la et bien ca fonctionne ! image/crazy.gif' class='bbc_emoticon' alt=' B) ' />

    Donc ce que j'en conclue c'est que j'accède aux éléments de mon tabbarController mais pas aux fonctions liées à  ce dernier ... oO ?!

    Ca me semble être une erreur de delegate, par conséquent je pense qu'il faudrait changé ou ajouter une attribution de delegate.



    Peut-être appliquer une delegate tabbar au splitView comme il est fait pour un navigationController dans l'AppDelegate sauf que en faisant et bien c'est simple le tabbar supplante le navigationController image/xd-laugh.gif' class='bbc_emoticon' alt='xd' />



    Donc je dois loupé une étape ou peut être simplement un ordre d'initialisation donc si vous avez une petite explication sous le coude elle seras (vraiment) la bienvenue image/smile.png' class='bbc_emoticon' alt=':)' />



    Puis pendant que j'y suis, une simple question technique : est ce que c'est judicieux d'utiliser pour les 2 masterView le même controller (c'est à  dire les même fichier .h et .m) et ainsi faire la différence entre les 2 via l'outlet de chaque tableview ?
    /*<br />
    test de différentiation de tableview gérer par un même controller<br />
    */<br />
    if(self.tableView1){<br />
    //traitement sur la tableView 1<br />
    } else { //traitement tableView 2 }<br />
    //et ainsi de suite en fonction du nombre de tableView<br />
    
  • AliGatorAliGator Membre, Modérateur
    'klozen' a écrit:


    Je m'aperçoit que la sub n'est même pas appelé. Bon direct je vais vérifier mon .h et je vais ajouter dans l'interface : (j'ai tellement de fois oublié d'ajouter ces delegate que maintenant dès que j'ai un problème de sub qui n'est pas appelé que je regarde ca direct)
    <br />
    @interface MasterViewController : UITableViewController &lt; UITabBarDelegate, UITabBarControllerDelegate&gt;<br />
    




    Cependant cela n'y change rien du tout image/crybaby.gif' class='bbc_emoticon' alt=' :'( ' /> image/crybaby.gif' class='bbc_emoticon' alt=' :'( ' />


    En faisant ça tu as déclaré que ton MasterViewController sait répondre aux protocoles UITabBarDelegate et UITabBarControllerDelegate. Donc tu déclares juste sa conformité à  ces protocoles, ce qui va dire que c'est correct d'appeler les méthodes de ces protocoles sur ton MasterViewController, il déclare qu'il saura y répondre si tu appelles ces méthodes dessus.



    Mais tu n'as pas pour autant indiqué à  ton TabBarViewController ou ton TabBar que son delegate c'est ton MasterViewController.

    Il faut bien faire l'association quelque part, pour qu'il sache de quelle TabBar il est le delegate. Ou plutôt dans l'autre sens que la TabBar sache quel objet (se conformant au UITabBarDelegate) est son delegate.



    Tu peux très bien imaginer avoir 2 TabBar dans ton appli, et également 2 UIViewController que tu auras déclaré se conformer au protocole <UITabBarDelegate>, il faut quand même que tu dises à  un moment que la TabBar 1 est associée au ViewController A ou B, et de même pour la TabBar 2.



    Donc il faut que tu affectes la propriété "delegate" de ta UITabBar à  l'instance de ton MasterViewController, pour qu'il en soit le delegué et que la TabBar appelle les méthodes sur ce dernier pour le prévenir quand un onglet a changé. (Ou affecter la propriété "delegate" de ton UITabBarController à  l'instance de ton MasterViewController, ça dépend si dans ta logique c'est la TabBar ou le TabBarViewController qui informe son delegate le MasterVC).



    Bien sûr pour faire cette affectation, tu peux le faire par code, ou tu peux le faire dans ton XIB/Storyboard, puisque la propriété "delegate" est en général marqué comme IBOutlet et est donc accessibles depuis InterfaceBuilder pour la connecter à  un objet directement par IB.
  • Oui exact autant pour moi j'ai confondu "conformité au protocole" et "associaition delegate"


    'AliGator' a écrit:


    Bien sûr pour faire cette affectation, tu peux le faire par code, ou tu peux le faire dans ton XIB/Storyboard, puisque la propriété "delegate" est en général marqué comme IBOutlet et est donc accessibles depuis InterfaceBuilder pour la connecter à  un objet directement par IB.




    Oui lorsque je visualise pour le splitview ainsi que pour la tabbar aucun delegate n'est enregistrer dans la liste des "connections inspector"

    Cependant il n'est pas possible d'affecter cet "Outlet" delegate à  l'un comme à  l'autre.



    Dans mon cas c'est dans le split que le tabbar doit etre associer en tant que delegate étant donné que le tabbar ne s'applique qu'a la masterView ou alors je fait fausse route dès cette réflexion ?

    Puis le fait d'avoir relier mon tabbarController directement au splitView avec la notion de MasterView Controller pour le segue ca ne lui suffit pas pour indiquer que le tabbar fait partit intégrante du splitView ?
  • klozenklozen Membre
    décembre 2012 modifié #12
    pourtant dans l'AppDelegate lors de l'initialisation il a par défaut (avec en commentaire ce que je pense des actions de chaque ligne) :
    <br />
    UISplitViewController *splitViewController = {UISplitViewController *)self.window.rootViewController; // pour définir le split en tant que root du projet<br />
    UINavigationController *navigationController &#33; [splitViewController.viewControllers lastObject]; //Défini un navigationController à  l&#39;aide d&#39;une vue déjà  détenu par le split par défaut<br />
    /*<br />
    D&#39;ailleurs si on fait un NSLog de ce splitViewController viewControllers on obtient un UITabBarController en idx 0 et un NavigationController en idx 1<br />
    */<br />
    splitViewController.delegate = (id)navigationController.topViewController; //défini le navigationController en delegate dans le splitView<br />
    //Par contre le topViewController a t-il une importance ?<br />
    <br />
    //Donc je me suis dit aller go on ajout la tabBar<br />
    UITabBarController *tabbar = [splitViewController objecteAtIndex:0]; //je récupère le tabbar comme pour le navigationController<br />
    splitViewController.delegate = (id)tabbar; //et je l&#39;ajoute en tant que delegate sauf que topViewControlle n&#39;existe pas ...<br />
    




    Cette solution ne fait pas d'erreur à  la compile mais du coup me cache mon bouton "Master" dans ma vue détailView mais on y a toujours accès via le landscape et cela fonctionne toujours. Cependant le tabbar n'est toujours pas delegate pour autant.
  • AliGatorAliGator Membre, Modérateur
    Heu là  tu affectes le delegate de splitViewController à  ton topViewController, puis plus tard à  ta tabBar (et le fait que tu sois obligé de le caster en "(id)" pour que ça passe montre bien qu'il y a un problème de cohérence). Concrètement là  tu dis que quand le SplitViewController veut informer son delegate de divers évènements (méthodes décrites dans le protocole UISplitViewControllerDelegate), c'est le tabbar qu'il va informer.



    Ce qu'il te faut faire c'est l'inverse, dire que quand ta TabBar fait des choses (change d'onglet, etc), indiquer qui elle doit prévenir (qui est son delegate), en l'occurrence ton SplitVC. Donc dire que tabbar.delegate = splitViewController. Pas l'inverse comme tu as fait.



    Concrètement quand le UITabBarController va changer d'onglet, sous le capot ça va faire [tabbar.delegate didSelectItem:newItem] donc appeller didSelectItem sur l'objet qui est affecté à  la propriété "delegate" du tabBar. Donc c'est bien la propriété delegate du tabBar qu'il faut associer à  ton SplitVC, tu veux que ce soit lui qui soit prévenu quand la TabBar change d'onglet. Pas le delegate de la SplitVC qu'il faut affecter.
  • okay je comprend mieux image/smile.png' class='bbc_emoticon' alt=':)' />



    Mais dans ce cas pourquoi il n'est pas possible dans le storyboard de définir le delegate de ma tabbarcontroller avec mon splitView ?

    c'est à  dire ctrl+clic sur mon tabbarController puis relancher sur mon splitViewController.
  • CéroceCéroce Membre, Modérateur
    Parce qu'il faut sous-classer UISplitViewController afin qu'il se conforme au protocole UITabBarDelegate.
  • ouch ... par contre l'action de "sous-classer" un controller ca ne me dit rien du tout (en tout cas dit comme ca) ...



    J'avais commencer à  faire un myTabbarViewController ce qui me permet de récupérer le changement d'onglet dans ce controller mais pas dans le masterview...
  • Si j'ai bien compris par défaut il y a une initialisation du splitview avec le rootViewController de l'appli et un navigation puis moi je doit ajouter un tabbar dans le splitView ce qui donnerais;



    (navigationViewController <---delegate--- splitViewController) <---delegate--- tabbarController <---delegate--- navigationController <---delegate--- uiTableView



    et celui qui me pose problème ca serais celui en gras sachant que ce qui est entre parenthèse est ce qui est fait par d"faut avec le template master détails de xCode.

    Sous classer c'est à  dire créer une classe perso qui colle au protocol du splitView et qui me permettra de coller également au protocol du UITabBarControllerDelegate ?
  • AliGatorAliGator Membre, Modérateur
    Bah après tu fais comme tu veux, c'est justement tout l'intérêt du système delegate, tu mets ton code de delegate ou tu veux.



    Avec le pseudo-schema que tu viens de faire tu est parti pour dire que tu veux que le delegate de ton tabbarController soit le splitViewController. Pour pouvoir faire cela, il faut que le splitViewController se conforme au protocole UITabBarControllerDelegate, et que tu implémentes dans splitViewController les méthodes "tabBarController:didSelectViewController:" et autres méthodes du protocole UITabBarControllerDelegate.



    Si ça ne t'arrange pas parce que ça t'impose de sous-classer UISplitViewController (pour pouvoir lui ajouter lesdites méthodes) et que tu n'avais pas prévu de le sous-classer, rien ne t'empêche d'utiliser quelqu'un d'autre comme delegate pour ton TabBarController, par exemple le navigationViewController. Il est déjà  delegate de ton UISplitViewController mais rien ne l'empêche d'être aussi delegate de UITabBarController aussi, et de gérer les deux.

    Comme tu as déjà  certainement sous-classé ce navigationViewController (c'est lui ton MasterViewController ?) pour lui rajouter des méthodes, tu peux en rajouter d'autres pour aussi implémenter UITabBarControllerDelegate. Et rajouter dans son .h qu'il se conforme au protocole UITabBarControllerDelegate. Et l'affecter via IB comme delegate de ton TabBarController (tout comme il est déjà  affecté aussi comme delegate du UISplitViewController).



    Dire qu'un objet A est delegate d'un autre objet B, c'est dire que quand B a quelquechose à  déléguer (ça peut être soit une question à  poser "est-ce que j'ai le droit de changer d'onglet ?", ou une information "ça y est j'ai changé d'onglet" ou ce genre de choses, ça dépend de ce qui est prévu dans le protocole en question), c'est A qu'il prévient, c'est à  A qu'il demande.

    Quand une TableView a besoin d'une cellule, c'est à  son dataSource qu'elle demande, quel que soit l'objet qui sert de dataSource. Quand tu cliques sur une cellule, c'est l'objet qui est affecté comme étant son delegate qu'elle prévient qu'une cellule a été cliquée. Quel que soit cet objet qui sert de delegate. Bah là  c'est pareil.

    Et rien n'empêche un objet A d'être à  la fois delegate de B (un UISplitViewController qui va prévenir son delegate quand le ViewController "Master" est masqué car l'iPad a tourné entre autres) et delegate de C (un UITabBarController qui va prévenir son delegate quand il a changé d'onglet pour afficher un autre ViewController) !
  • Voila ca c'est de la bonne explication !! image/clap.gif' class='bbc_emoticon' alt=' :D ' />

    Franchement merci d'avoir pris le temps de m'expliquer ce principe qui était un peu (trop) flou dans mon esprit image/wink.png' class='bbc_emoticon' alt=';)' />



    Par contre juste un hic par rapport au fait que le navigationController est sous classer car delegate du splitView.

    Je suppose que ca fait référence à  cette ligne
    <br />
    splitViewController.delegate = (id)navigationController.topViewController;<br />
    




    Mais il vient d'ou ? Il est juste présent dans le code car indispensable au splitView ? (car pas de trace dans le storyboard)

    Ce navigationController est la car c'est le template de master detail de xCode qui l'a crée...

    Mais pour moi mon RootController c'est mon splitView ...

    Le fait que le navigationController soit le delegue de mon splitView ca me permet de récupérer les infos de ma masterView et détailView ? Donc un splitView c'est 2 vues séparées qui répondent au protocole du splitView et rendent des compte au navigationController pour gérer les actions inhérentes tel que le passage du mode portrait au landscape, etc ?



    Du coup pour ce principe de delegate je comprend mieux pourquoi par exemple il faut relier un textField à  la vue qui le contient image/tongue.png' class='bbc_emoticon' alt=':P' /> ou encore comme tu le dit une cell et sa tableView image/smile.png' class='bbc_emoticon' alt=':)' />
  • klozenklozen Membre
    décembre 2012 modifié #20
    Pour le delegate je suppose qu'il faut définir ca dans l'appDelegate comme c'est fait pour le split en faisant quelques chose ressemblant à  ca :
    UITabBarController *tabbar = [splitViewController.viewControllers objectAtIndex:0]; //je récupère le tabbar présent dans mon splitView pour la masterview (idx 0)<br />
    UINavigationController *myNav = [tabbar.viewControllers lastObject]; //Dans ce tabbar 2 navigationController car 2 onglet je suppose.<br />
    //Je fait comme pour le split je récupère uniquement le dernier<br />
    tabbar.delegate = (id)myNav.topViewController; //J&#39;attribue le delegate comme ca a été fait pour le split<br />
    


    et du coup ca fonctionne je récupère bien les évènement du tabbarController du style
    -(BOOL)tabBarController:(UITabBarController *)tabBarController shoulSelectViewController ........<br />
    


    mais toujours pas l'évènement didSelectItem qui lui découle du tabBar ...

    Mais si on gère le tabbarController on ne devrait pas gérer en même temps le tabbar à  l'intérieur ?!
  • CéroceCéroce Membre, Modérateur
    'klozen' a écrit:


    il faut relier un textField à  la vue qui le contient


    Non, pas à  sa vue, à  son view controller, qui va se conformer au protocole UITextFieldDelegate.



    Une UIView est un objet qui s'affiche à  l'écran et gère les événements. Un UIViewController gère une UIView racine (qui elle même peut contenir des UIView enfants). Même si par abus de langage on dit parfois que "le view controller s'affiche", concrètement c'est sa vue qui s'affiche.



    Tu comprendras que le délégué du text field n'est pas obligatoirement un view controller (même si c'est souvent le cas), ça pourra être n'importe quel objet se conformant au protocole.
  • Je pense avoir compris cependant l'intégration du tabbar ne se faisant pas correctement je l'est pour le moment mis à  l'écart.

    J'ai donc remodelé mon storyboard afin que ca donne ceci :
  • CéroceCéroce Membre, Modérateur
    décembre 2012 modifié #23
    Je pense que le problème est que tu es parti sur Storyboard alors que tune maà®trises pas. les concepts sous-jacents. On lit beaucoup ici "Storyboard est un bon outil pour moi, qui suis débutant", alors que c'est tout le contraire. C'est un outil qui fait gagner du temps aux utilisateurs avancés.

    UISplitViewController n'est pas bien compliqué à  utiliser (sauf quand on modifie la barre de boutons, mais c'est un cas particulier).
  • il faudrait donc que je fasse mon projet à  l'aide de fichier .xib du type http://www.raywenderlich.com/1040/ipad-for-iphone-developers-101-uisplitview-tutorial ? pour une fois avoir compris passer au storyboard ?
  • CéroceCéroce Membre, Modérateur
    Tout ce que je peux te dire, c'est que quand dans la formation que je donne, je n'enseigne pas l'utilisation de Storyboard. Nous créons tous les contrôleurs et faisons les liens entre eux dans le code. Ton expérience me donne raison.



    À l'issue de la formation, j'encourage les stagiaires à  s'intéresser à  Storyboard seuls de leur côté. Une fois les concepts sous-jacents assimilés, l'utilisation de Storyboard se révèle simple et on comprend ses limitations. Si jamais Storyboard ne répond pas au besoin (ce qui arrive souvent), il nous reste la possibilité de gérer les choses à  la mano.
  • klozenklozen Membre
    janvier 2013 modifié #26
    Je me permet de déterrer ce topic car je suis en plain dans la gestion d'un tabbar dans mon application avec fichier .xib.

    J'ai donc 2 vues initialiser dans l'appDelegate avec l'ajouts de ces vues dans le viewcontrollers du tabbar initialisé également dans l'appdelegate, etc. Tout fonctionne, j'ai bien défini le delegate pour récupérer les évènements du tabbarViewcontroller dans mes vue.

    Par contre je ne peut pas récupérer les évènements du tabbar du type -(void)tabbar didSelectItem est ce normal ? La tabbar n'est pas lié au tabbar ? Il faut que l'ajout dans les fichier xib pour pouvoir récupérer ces évènements ?
  • CéroceCéroce Membre, Modérateur
    A priori, le délégué de la UITabBar est le UITabBarController. Ceci parce que le contrôleur a besoin d'être informé du changement d'onglet pour afficher la bonne vue.

    Si tu veux savoir quand l'utilisateur change d'onglet, mets-toi en délégué du UITabBarController.
  • Oui c'est ce que je pensais aussi. Cependant je suis déjà  en délégué de mon UITabBarController puisque je récupère les évènements du type -(void)tabbarcontroller selected...:(UIViewController*)viewcontroller {...} (je n'est pas le code sous la main et je ne me souviens plus de la syntaxe exact mais j'arrive à  afficher (NSLog) la vue sur laquelle on arrive suite à  la sélection d'un onglet) mais la sub sur le tabbar n'est pas appelé...
  • CéroceCéroce Membre, Modérateur
    'klozen' a écrit:


    mais la sub sur le tabbar n'est pas appelé...


    Rien compris.
  • dans ma UIViewController qui sert de delegate a mon UITabBarController je passe bien dans les sub du type -(void)tabbarController ... correspondant au protocol UITabBarControllerdelegate mais jamais dans les sub -(void)tabbar .... qui doivent correspondre au protocol UITabBarDelegate.
  • CéroceCéroce Membre, Modérateur
    Oui, c'est normal.



    Un objet appelle les méthodes déléguées de son... délégué.

    Une UITabBar appelle les méthodes du protocole UITabBarDelegate de son délégué.

    Un UITabBarController appelle les méthodes du protocole UITabBarControllerDelegate de son délégué.



    Le délégué du UITabBarController est ta sous-classe de UIViewController.

    Mais le délégué de la UITabBar est le UITabBarController.
Connectez-vous ou Inscrivez-vous pour répondre.