Plusieurs UITableViews dans le même controller

Hello,

Je ne rencontre pas de problèmes actuellement, mais je me posais une question.

Quel est la façon la plus "propre" de mettre 2 (ou plus) UITableView (ou objets du meme type avec DataSource et Delegate) dans un meme controller?


Solution 1: Mettre des if dans les méthodes de delegate/dataSource (solution assez limite).

Solution 2: Créer une classe qui hérite de tableView et qui est son propre delegate/dataSource (la le principe de delegate n'est pas "respecté")

Solution 3??


Merci d'avance pour vos retours d'expériences ou avis :)


Réponses

  • Tu peux aussi créer une classe-datasource pour chaque table view.

    Ton controller crée les table view et les classes-datasource.


  • Autant implémenter la solution 2 non?  ::)

  • AliGatorAliGator Membre, Modérateur
    Par flemme parfois je fais la solution 1 bien qu'elle ne soit pas terrible, mais certainement pas la solution 2 (car bye-bye MVC et pattern delegate). Plutôt la solution 3 ou 4 :

    - Solution 3 : Créer une classe dédiée qui serve de dataSource et delegate, plutôt que d'utiliser ton UIViewController comme dataSource et delegate de tes tableViews. Ainsi tu peux dans ton viewDidLoad par exemple, créer une instance de MyDataSource1 et l'affecter à  maTableView1.dataSource, et créer une instance de MyDataSource2 et l'affecter à  maTableView2.dataSource. Bref, avoir des dataSources qui sont des objets différents (différents de ton UIViewController) pour tes 2 TableViews plutôt que faire qu'elles utilisent le même objet (ton ViewController) comme dataSource.

    - Solution 4 (sans doute la meilleure, d'autant qu'elle permet une archi plus propre car mieux découpée avec chacun sa responsabilité) : utiliser le View Controller Containement API. Autrement dit avoir un UIViewController dédié qui ne va s'occuper que de gérer la UITableView 1, un autre qui va s'occuper de la UITableView 2, et tu ajoutes ces 2 UIViewController en childViewController de ton UIViewController parent. Ce qui est même encore mieux avec cette solution c'est que tes 2 childViewControllers qui pilotent chacun une tableView, ça peut être directement des UITableViewController, te permettant de profiter de tous les avantages du comportement des UITableViewControllers (auto-keyboard-avoiding, auto-deselect, etc)
  • Merci Ali, 

    La solution 3 me parait viable. Par contre, et ça doit être un facteur personnel mais j'aime pas trop les container de la solution 4.

    Après ça n'engage que moi, mais même en partant du principe que t'as un model pour toute ton appli les communications entre le container et sa vue parente sont compliquées.


    Admettons, une archi ou tu as un UIViewController avec une table view, si tu veux mettre (par exemple et j''exagère dans l'exemple), deux container qui contiennent un bouton chacun qui doivent mettre à  jour la tableView de la vue parente, c'est la galère (ou au moins pas évident)!

    Tu vas devoir implémenter un delegate, ou poster une notif etc... Non?




  • Merci Ali, 

    La solution 3 me parait viable. Par contre, et ça doit être un facteur personnel mais j'aime pas trop les container de la solution 4.

    Après ça n'engage que moi, mais même en partant du principe que t'as un model pour toute ton appli les communications entre le container et sa vue parente sont compliquées.


    Admettons, une archi ou tu as un UIViewController avec une table view, si tu veux mettre (par exemple et j''exagère dans l'exemple), deux container qui contiennent un bouton chacun qui doivent mettre à  jour la tableView de la vue parente, c'est la galère (ou au moins pas évident)!

    Tu vas devoir implémenter un delegate, ou poster une notif etc... Non?




     


    Non ce n'est pas galère, la galère c'est d'avoir tout dans le même contrôleur et un code non maintenable. 


     


    Oui tu utilises simplement la delegation pour une communication enfant-père, ensuite le père ( le container) saura transmettre les données nécessaires aux autres enfants.


     


    Solution 5 :


    Utiliser une collectionView, je pense qu'on peut tout faire avec un custom Layout.


  • Non ce n'est pas galère, la galère c'est d'avoir tout dans le même contrôleur et un code non maintenable.




    Si c'est galère, mais pas à  cause de la communication entre controllers.


     


    La solution 4 est sans doute la plus logique mais elle est mal implémentée par Apple.


    On ne peut pas facilement la mettre en place dans un XIB ou storyboard.

    Par code, il faut appeler soi-même plusieurs méthodes pour que cela fonctionne bien et c'est un peu confus.



    UIViewController* vc = // whatever; this the initial child view controller
    [self addChildViewController:vc]; // "will" is called for us
    [self.view addSubview: vc.view];
    // when we call "add", we must call "did" afterwards
    [vc didMoveToParentViewController:self];
    vc.view.frame = // whatever, or use constraints


    L'intérêt qu'on en retire n'est pas évident par rapport  à  la solution 3, où on maitrise bien ce qui se passe.

     

    Après il faut vraiment savoir de quoi on a besoin et faire le minimum en fonction du besoin.

    -Un datasource pour fournir les cellules.

    -un datasource + un delegate pour répondre à  des interactions avec les cellules.

    -un controller car en fait on veut aussi gérer quelques view annexes en plus de la tableview.

     

     

    Parmi les 1 à  5, toutes les solutions sont envisageables en fonction de la quantité de code nécessaire pour gérer les tableview, des chances de réutilisation et d'évolution qu'on envisage.

     

    La solution 2 bien que pas MVC, je l'utilise pour obtenir une vue totalement encapsulée et réutilisable, un peu comme un composant spécialisé. En plus c'est simple à  mettre en oeuvre dans les XIB, il suffit de placer une TableView et donner sa classe.

    Il y a une tension entre le principe de responsabilité (chacun doit gérer ses affaires) et le MVC où la gestion est déléguée au controller. Il faut jongler entre les deux en fonction des situations.
  • AliGatorAliGator Membre, Modérateur

    Admettons, une archi ou tu as un UIViewController avec une table view, si tu veux mettre (par exemple et j''exagère dans l'exemple), deux container qui contiennent un bouton chacun qui doivent mettre à  jour la tableView de la vue parente, c'est la galère (ou au moins pas évident)!
    Tu vas devoir implémenter un delegate, ou poster une notif etc... Non?

    Oui tu vas devoir utiliser des mécanismes type delegate pour faire communiquer tes ViewControllers parent/enfant, mais ça te permet d'avoir une architecture plus propre (dépendances faibles grâce à  l'utilisation des protocoles qui n'exposent que ce qui est nécessaire), un code mieux réparti (pas de mélange de code entre des trucs qui ne sont nécessaires qu'à  la TableView1 et que la TableView2 n'a pas à  connaà®tre mais risquerait sinon d'utiliser quand même par erreur si tout le code est dans un UIViewController géant) et plus agréable à  lire (moins volumineux, ça évite un gros UIViewController de 2000 lignes et répartit ce code de 2000 lignes entre le parent et les 2 enfants, donc moins "mastoc", etc, donc tu as quand même beaucoup d'avantages qui vont faciliter la lisibilité.



    On ne peut pas facilement la mettre en place dans un XIB ou storyboard.

    Heu si on peut tout à  fait le faire sans souci dans un Storyboard, il suffit de glisser un ContainerView dans la vue du VC parent, et le Storyboard te met automatiquement un Segue "Container" qui va te permettre de pointer vers le ViewController fils que tu veux mettre à  cet endroit dans le parent.

    Par code, il faut appeler soi-même plusieurs méthodes pour que cela fonctionne bien et c'est un peu confus.

    Là  je suis assez d'accord, au début à  chaque fois j'allais faire un tour dans le Programming Guide pour être sûr de savoir quand appeler "will" et quand appeler "did", car il y en a toujours un des deux à  appeler et pas l'autre et dans le bon ordre. Maintenant j'ai créé un snippet Xcode que j'ai plus qu'à  drag & drop dans mon code donc je ne me pose plus trop cette question, mais c'est vrai que les premières fois c'est confus. On s'y fait, et puis c'est que 4 lignes de code à  écrire qu'une seule fois dans ton VC parent (et encore, si tu fais ça en Storyboard t'en as même pas besoin) faut pas que ce soit ça qui te bloque pour adopter la solution non plus.

  •  


     


    Heu si on peut tout à  fait le faire sans souci dans un Storyboard, il suffit de glisser un ContainerView dans la vue du VC parent, et le Storyboard te met automatiquement un Segue "Container" qui va te permettre de pointer vers le ViewController fils que tu veux mettre à  cet endroit dans le parent.

     


    C'est tout à  fait vrai. Mais si on souhaite avoir plusieurs view controllers (ce qui n'est pas la demande suggérée du topic) là  on ne peut plus le faire par Storyboard, du moins je n'ai pas trouvé. La seule solution c'est de mettre en pratique par code.


     


    Sinon, je suis de l'avis de la solution 1. Non pas que je l'aime bien mais je ne pense pas qu'on puisse avoir plus de 2 table View dans un controller auquel cas je pense qu'il faudrait revoir le design et l'ergonomie de l'application. Du coup mettre des if revient à  être la plus simple à  mon sens.



  • Non pas que je l'aime bien mais je ne pense pas qu'on puisse avoir plus de 2 table View dans un controller auquel cas je pense qu'il faudrait revoir le design et l'ergonomie de l'application.




    Autant pour une appli iPhone c'est vrai que c'est bizarre d'avoir deux tableview sur le même écran.

    Autant sur une appli iPad cela peut être courant, mais dans ce cas je serais de l'avis d'utiliser la solution 4, c'est à  dire avec le containerParent et les childViewController.

     


Connectez-vous ou Inscrivez-vous pour répondre.