SegmentedControl, TableView, UIView, MVC...

muqaddarmuqaddar Administrateur
13:20 modifié dans API UIKit #1
Bonsoir les amis,

J'ai un petit soucis de conception et de compréhension...

J'ai une UITableView dans un UITableViewController qui se charge parfaitement avec les données provenant d'une autre classe. Jusque là  tout va bien.

Cette UITableView fait des push dans la méthode delegate adéquate comme ceci vers un autre controller de vue :

<br />- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {<br />	<br />	// load the content view controller with its nib file<br />	ContentViewController *contentViewController;<br />	contentViewController = [[ContentViewController alloc]initWithNibName:@&quot;ContentView&quot; bundle:nil];<br /><br />	// send data to view controller<br />	int itemIndex = [indexPath indexAtPosition: [indexPath length] - 1];<br />	NSDictionary *currentItem = [NSDictionary dictionaryWithDictionary:[items objectAtIndex: itemIndex]];<br />	[contentViewController setItem:currentItem];<br />	[contentViewController setItems:items];	<br />	<br />	// load the view now !<br />	[[self navigationController] pushViewController:contentViewController animated:YES];<br /><br />	// release controller<br />	[contentViewController release];<br />}<br /><br />


J'ai donc dans mon contentViewController des accesseurs (items, item) délcarés en propriétés.

Mon contentViewController fait son boulot avec ses outlets et affiche ce qu'il faut dans sa vue.

Maintenant, j'ai un navigationSegmentedControl dans cette vue pour passer directement d'un item de ma tableview à  l'autre pour ne pas avoir à  revenir à  la tableView.

Je ne sais pas bien comment le gérer proprement et en "bon MVC" qui se respecte. Ce navigationSegmentedControl appelle l'action suivante :

<br />- (IBAction)segmentedControlAction:(id)sender {<br />	switch([sender selectedSegmentIndex]) {<br />		case 1: <br />		{<br />			NSLog(@&quot;1&quot;);<br />		}<br />		case 0:<br />		{<br />			NSLog(@&quot;0&quot;);<br />		}<br />	}<br />}<br />


En fait, je me pose des questions de logique. Le but du jeu est de récupérer l'index de l'item en cours d'affichage pour pouvoir afficher l'item suivant ou précédent.

Déjà  l'index de cet item doit il être "setté" juste avant le push de la tableView ?
Y-a-t-il un moyen de le récupérer à  partir de :

<br />NSArray * viewControllers=[self.navigationController viewControllers];<br />


Plus grave : est-ce que je fais mon setItem au bon endroit dans la méthode delegate de la tableView ou bien devrais-je plutôt juste envoyer mon index depuis là -bas, puis récupérer le items array général depuis viewDidLoad de la vue contentViewController ? ET enfin récupérer le bon dico à  partir de ces 2 infos dans viewDidLoad ?

Enfin, dois-je récupérer mon nib et le charger à  chaque fois que je switche dans le segmentedControlAction ?

<br />ContentViewController *contentViewController;<br />	contentViewController = [[ContentViewController alloc]initWithNibName:@&quot;ContentView&quot; bundle:nil];<br />


Réponses

  • muqaddarmuqaddar Administrateur
    13:20 modifié #2
    J'ai peut-être pas été assez clair sur certains points ?
    (en fait je me suis inspiré du tuto de Philippe qui n'a pas l'air là  ces temps-ci...) ;-)

    N'hésitez pas si vous voulez que je développe un passage.
  • AliGatorAliGator Membre, Modérateur
    13:20 modifié #3
    Pour moi ton ViewController qui affiche ton détail (et à  côté duquel tu as ton SegmentedControl) doit avoir 2 variables grosso modo : un dataSource, et un
    indexPath indiquant où il doit aller chercher ses infos dans la source.

    Au moment où tu le push (suite à  un clic sur un item dans la vue parente), tu fixes l'indexPath pour correspondre à  la sélection que tu as faite.
    Au moment où tu changes la sélection de ton SegmentedControl, il suffit d'adapter ton indexPath pour refléter le nouveau "chemin d'accès" des données pour qu'il aille chercher les infos du nouvel item (et de faire un reloadData ensuite bien sûr).

    Ca te semble jouable vu ton archi d'appli actuelle ? (J'ai pas tout lu de ta description j'ai du mal à  voir le truc dans son ensemble)
  • muqaddarmuqaddar Administrateur
    avril 2009 modifié #4
    Oui tu as compris ce que je veux faire.

    Je suis OK sur le fait d'envoyer l'indexPath.

    Ce que je voulais savoir surtout c'est s'il faut envoyer le array de sources à  la vue détaillée depuis le controller tableView au moment du push (et puis par la suite à  chaque changement de segmentedControl ?), ou bien s'il faut l'absorber sur le TableViewController (avec un accesseur get ?) depuis la vue détaillée dans le viewDidLoad par exemple ?! C'est purement un problème objet là  je crois.
  • AliGatorAliGator Membre, Modérateur
    13:20 modifié #5
    Théoriquement il ne faut pas passer ton NSArray de sources, mais juste passer ton objet qui te sert de dataSource... dataSource qui sera commun pour le coup à  tes viewControllers, mais te renverra la bonne sous-partie en fonction de l'indexPath courant.

    Ou alors tu as des dataSource distincts (tu te sers de tes UITableViewControllers comme datasource de tes UITableViews), et dans ce cas passer tout le tableau de données à  ton dataSource c'est pas méchant, car ça ne fera qu'un retain de plus dessus (donc juste augmenter son retainCount de 1), ça va pas en faire une copie non plus (parce que là  par contre, faire une copie de tout ton tableau de données, côté utilisation mémoire ça serait bof !)
  • muqaddarmuqaddar Administrateur
    avril 2009 modifié #6
    dans 1239876449:

    Théoriquement il ne faut pas passer ton NSArray de sources, mais juste passer ton objet qui te sert de dataSource... dataSource qui sera commun pour le coup à  tes viewControllers, mais te renverra la bonne sous-partie en fonction de l'indexPath courant.

    Ou alors tu as des dataSource distincts (tu te sers de tes UITableViewControllers comme datasource de tes UITableViews), et dans ce cas passer tout le tableau de données à  ton dataSource c'est pas méchant, car ça ne fera qu'un retain de plus dessus (donc juste augmenter son retainCount de 1), ça va pas en faire une copie non plus (parce que là  par contre, faire une copie de tout ton tableau de données, côté utilisation mémoire ça serait bof !)


    J'ai du mal à  suivre là ...
    En fait, j'ai 2 tableView gérées par 2 tableViewControllers qui doivent envoyer les infos à  la même UIViewController.

    Dans mon UIViewController, je peux récupérer la vue parente, donc la tableViewController grâce à  navigationController. Je pensais donc pouvoir récupérer le datasource, mais ça m'oblige à  faire un truc du genre :

    <br />// get the controllers hierarchy<br />NSArray *viewControllers = [self.navigationController viewControllers];<br />// get the previous controller<br />NSUInteger controllerIndex = [viewControllers indexOfObject:self];<br />UITableViewController *tableViewController = [viewControllers objectAtIndex:controllerIndex-1];<br />id datasource = [[tableViewController topicsTable] dataSource];<br />
    


    J'ai l'impression que je suis vraiment à  côté de la plaque... alors qu'il me paraà®t 100 fois plus simple de faire un [tableViewController items] pour récupérer directement mon array de items ?
    Parce ce que moi ce qui m'intéresse, c'est mon tableau de ressources et non mon datasource qui ne m'est utile que pour la tableView et le tableViewController ?!

    De toute façon, même en récupérant le dataSource, je ne sais pas si je peux récupérer mes items qui l'alimentent ?
  • AliGatorAliGator Membre, Modérateur
    13:20 modifié #7
    dans 1239904104:
    J'ai l'impression que je suis vraiment à  côté de la plaque... alors qu'il me paraà®t 100 fois plus simple de faire un [tableViewController items] pour récupérer directement mon array de items ?
    Parce ce que moi ce qui m'intéresse, c'est mon tableau de ressources et non mon datasource qui ne m'est utile que pour la tableView et le tableViewController ?!

    De toute façon, même en récupérant le dataSource, je ne sais pas si je peux récupérer mes items qui l'alimentent ?
    Ben tu peux toujours passer à  tes tableViewControllers ton tableau d'items (typiquement au moment où tu crées des UITableViewControllers, juste avant de faire le "push", tu affectes à  une variable d'instance de ta sous-classe de UITableViewController ton tableau de données
    @interface MyTableViewController : UITableViewController<br />{<br />&nbsp;  NSArray* items;<br />&nbsp;  ...<br />}<br />@property (nonatomic, retain) NSArray* items;<br />...<br />@end<br /><br />...<br />-(void)blabla<br />{<br />&nbsp; MyTableViewController* tvc = [[MyTableViewController alloc] init...];<br />&nbsp; tvc.items = self.items;<br />&nbsp; [self.view pushViewController:tvc animated:YES];<br />&nbsp; [tvc release];<br />}
    
    Maintenant, ça c'est la solution rapide pour coller apparemment à  ton besoin et ton architecture...
    Mais j'avoue que je trouve ça bizarre, enfin j'ai du mal à  cerner ton architecture (t'as pas des captures d'interface ou un petit graphe OmniGraffle pour montrer le principe en plus parlant ?)... Que tu passes ton tableau de données entre tes divers dataSource (utilisant les mêmes données sources mais n'allant pas chercher au même endroit dans ton NSArray pour le même indexPath selon la tabeView à  remplir), mais que tu cherches à  "récupérer" ton tableau d'items ?

    Enfin c'est p'tet une mauvaise interprétation de ma part, en fait j'ai l'impression que tu veux que tes TableViewControlleurs "récupèrent" ton tableau d'items, au lieu que tu leur passes ton tableau d'item à  l'initialisation ? En fait c'est le "sens" dans lequel tu sembles vouloir "envoyer" tes infos qui me gène, tu sembles vouloir faire en sorte que tes TableViewControllers "demandent" le tableau des items... alors qu'on est sensé leur "fournir" et que c'est à  eux que tes tableviews vont "demander" ensuite les données pour chaque cellule... donc quand toi tu dis que tu veux que tes tableViewControlleurs "récupèrent" ton tableau d'items, moi je dis plutôt que tu dois leur "fournir" à  l'initialisation.
  • muqaddarmuqaddar Administrateur
    13:20 modifié #8
    En fait c'est vraiment plus simple.  :p

    Voilà  mon architecture.
    J'ai un appDelegate, un xmlParser, 2 tableViewController et 1 UIViewController.

    Ce qui nous intéresse ici :
    un tableViewController qui envoie les infos détaillées à  afficher à  l'UIViewController.

    Le tableViewController charge l'array d'items dans une tableView via les méthodes delegate.
    Au moment du push, il envoie l'index de l'item que l'on doit visualiser. On était d'accord sur ce point.

    La question principale de conception était la suivante : faut-il envoyer l'array d'items géré dans UITableViewController au moment du Push ou bien faut-il le récupérer dans le UIViewController en s'appuyant sur un accesseur get placé dans UITableViewController ?

    Je m'oriente plutôt vers la seconde méthode d'autant plus que c'est plus logique vu qu'après, une fois dans le UIViewController, je vais jongler avec cet array d'items et l'index de l'item en cours d'affichage pour afficher les items précédents ou suivants par le segmentedControl.

    Donc je pense que j'ai un peu la réponse à  ma question, mais je voulais m'assurer que c'était pas trop mauvais niveau MVC vu que je débute sur l'iphone.

  • AliGatorAliGator Membre, Modérateur
    13:20 modifié #9
    dans 1239911086:

    En fait c'est vraiment plus simple.  :p

    Voilà  mon architecture.
    J'ai un appDelegate, un xmlParser, 2 tableViewController et 1 UIViewController.

    Ce qui nous intéresse ici :
    un tableViewController qui envoie les infos détaillées à  afficher à  l'UIViewController.
    Bon j'ai encore du mal, mais déjà  je viens de réaliser que ton architecture hiérarchique était sous la forme TableViewController (tvc1) --> TableViewController (tvc2) --> UIViewController (detailsVC), où la UIViewController sert à  afficher sans doute le "détail" (vue détaillée) j'imagine, alors qu'avant je pensais que c'était dans l'autre sens, UIViewController contenant par exemple un bouton qui déclenait l'affichage de tvc1 qui elle affichait tvc2, et rien derrière. Bon, donc ton vc est sensé afficher le détail de ton tvc1, ok.

    T'aurais pas pu dire dès le début que ta tvc1 était la liste des posts osx-dev, tvc2 la liste des messages du post choisi dans tvc1, et detailsVC l'affichage du post sélectionné ? J'aurais mieux compris dès le début :P  ;) ;D
    dans 1239911086:
    Le tableViewController charge l'array d'items dans une tableView via les méthodes delegate.
    Heu c'est justement l'emploi de ces termes qui me gêne là ... ça va pas dans ce sens là , mais dans le sens inverse normalement !! C'est pas le TableViewController qui charge l'array d'items dans la tableView, c'est la tableView qui demande les items au TableViewController. Et c'est pas via les méthodes de delegate, mais de dataSource.

    Je sais pas si c'est ce que tu voulais dire mais que tu n'utilises pas les bons termes, ou si tu fais effectivement tout à  l'envers... ou si c'est moi qui suis trop "exigeant" sur les termes et le vocabulaire à  utiliser, mais justement on parle d'architecture, donc faut bien qu'on soit d'accord sur l'organisation des choses, de comment ça fonctionne et dans quels sens vont les messages !

    dans 1239911086:

    Au moment du push, il envoie l'index de l'item que l'on doit visualiser. On était d'accord sur ce point.
    Ca ok, au moment où tu crées l'instance de ton PostViewController, tu affectes l'index de l'item à  visualiser à  une variable d'instance de ce PostViewController avant de le pusher.

    dans 1239911086:
    La question principale de conception était la suivante : faut-il envoyer l'array d'items géré dans UITableViewController au moment du Push ou bien faut-il le récupérer dans le UIViewController en s'appuyant sur un accesseur get placé dans UITableViewController ?

    Je m'oriente plutôt vers la seconde méthode d'autant plus que c'est plus logique vu qu'après, une fois dans le UIViewController, je vais jongler avec cet array d'items et l'index de l'item en cours d'affichage pour afficher les items précédents ou suivants par le segmentedControl.
    Oui, à  mon avis le mieux c'est que ton PostsTableViewController (celui qui push ton UIViewController) soit le dataSource dudit UIViewController, et quand tu as besoin de connaà®tre les données à  afficher dans ton PostViewController, ce dernier demande à  son dataSource (au PostsTableViewController quoi) le texte pour le post n°index (où index est la variable d'instance du PostViewController que tu as initialisé avant de le pusher... et que tu as potentiellement modifié par la suite à  l'aide de ton SegmentedControl)...

    En faisant comme ça c'est propre, ça respecte le pattern du dataSource, et tu ne demandes que ce dont tu as besoin.
    Après que le dataSource de ton UIViewController (donc en somme ton PostsTableViewController) fournisse d'un coup un NSDictionary représentant le post demandé (son titre, son auteur, son texte...), genre appeler une méthode du style "-(NSDictionary*)postInfoForIndex:(NSUInteger)index" sur ton dataSource pour récupérer toutes les infos du post index... ou qu'il fournisse " un peu plus à  l'image d'un UITableViewDataSource " chaque item à  la demande (donc tu appellerais "titleForPostIndex:", "textForPostIndex:" et "authorForPostIndex:" chacun son tour sur ton dataSource pour obtenir les informations), ça se vaut, à  toi de voir...
  • AliGatorAliGator Membre, Modérateur
    avril 2009 modifié #10
    Un peu de code vaut mieux qu'un long discours... ça sera peut-être encore plus clair comme ça (j'ai supposé que j'avais vu juste en parlant des PostsTableViewController listant les posts d'un sujet d'osx-dev, et du PostDetailViewController ton UIViewController affichant le détail post sélectionné... ;))
    // Protocole qui sera implémenté par le dataSource de ton UIViewController pour récupérer les infos à  afficher dans sa vue détaillée<br />@protocol PostDetailsViewDataSource<br />-(NSString*)authorForPostAtIndex:(NSUInteger)index;<br />-(NSDate*)dateForPostAtIndex:(NSUInteger)index;<br />-(NSString*)textForPostAtIndex:(NSUInteger)index;<br />@end<br /><br /><br /><br /><br />/////////////////////////// TableViewController des posts ///////////////////////////<br /><br />// NB : c&#39;est lui qui sera le &quot;dataSource&quot; de ton &quot;PostDetailsViewController&quot;<br />// (le UIViewController affichant le détail)... donc c&#39;est pour ça qu&#39;il implémente le @protocol ci-dessus<br /><br />@interface PostsTableViewController : UITableViewController &lt;PostDetailsViewDataSource&gt;<br />{<br />  NSArray* posts; // contient un tableau de NSDictionary, chaque NSDico ayant les clés &quot;author&quot;, &quot;date&quot; et&quot; text&quot;, par exemple<br />&nbsp; ...<br />}<br />...<br />@end<br /><br /><br />@implementation PostsTableViewController<br />...<br />#pragma mark UITableViewDataSource implementation<br />...<br />-(UITableViewCell*)cellForRowAtIndexPath:(NSIndexPath*)indexPath<br />{<br />   UITableViewCell* cell = [... dequeueCellWithReuseIdentifier:...]<br />   if (!cell) {<br />      cell = ... // alloc/init de la cell with reuseIdentifier, etc... classique quoi<br />   }<br />   NSDictionary* postData = [posts objectAtIndex:indexPath.row];<br />   NSString* author = [postData objectForKey:@&quot;author&quot;];<br />   NSDate* date = [postData objectForKey:@&quot;date&quot;];<br />   NSString* text = [postData objectForKey:@&quot;text&quot;];<br />  // exemple : générer le texte de la cellule pour avoir un extrait du début du texte, sans formattage HTML<br />   cell.text = [NSString stringWithFormat:@&quot;%@, %@&#092;n%@&quot;,author, date, [self stripHTMLTags:text length:50]]; <br />}<br /><br />#pragma mark UITableViewDelegate implementation<br />-(void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath<br />{<br />  PostDetailViewController* pdvc = [[PostDetailViewController alloc] initWithNibName:@&quot;PostDetail&quot;];<br />  pdvc.postIndex = indexPath.row;<br />  pdvc.dataSource = self;<br />  [self.view pushViewController:pdvc animated:YES];<br />  [pdvc release];<br />}<br /><br />#pragma mark PostDetailsViewDataSource implementation<br />// retourner pour chacun la bonne valeur extraite du NSArray &quot;posts&quot;, selon la valeur de &quot;index&quot;<br />-(NSString*)authorForPostAtIndex:(NSUInteger)index { ... }<br />-(NSDate*)dateForPostAtIndex:(NSUInteger)index { ... }<br />-(NSString*)textForPostAtIndex:(NSUInteger)index { ... }<br />...<br />@end<br /><br /><br /><br /><br />/////////////////////////// PostDetailsViewController, ton UIViewController de détails ///////////////////////////<br /><br />@interface PostDetailViewController : UIViewController<br />{<br />  id&lt;PostViewDataSource&gt; dataSource;<br />  NSUInteger postIndex;<br />}<br />@property(nonatomic, assign) id&lt;PostViewDataSource&gt; dataSource;<br />@property(nonatomic, assign) NSUInteger postIndex;<br />-(void)reloadData;<br />-(IBAction)segmentedControlChanged:(id)sender;<br />@end<br /><br /><br />@implementation PostDetailViewController<br />@synthesize postIndex, dataSource;<br /><br />-(void)setPostIndex:(NSUInteger)index<br />{<br />  postIndex = index;<br />  [self reloadData];<br />}<br />-(void)setDataSource:(id&lt;PostViewDataSource&gt;)obj<br />{<br />  dataSource = obj;<br />  [self reloadData];<br />}<br /><br />-(IBAction)segmentedControlChanged:(id)sender<br />{<br />  self.postIndex = [sender selectedSegmentIndex];<br />}<br /><br />-(void)reloadData<br />{<br />  authorLabel.text = [dataSource authorForPostAtIndex:index];<br />  dateLabel.text = [dateFormatter stringFromDate: [dataSource dateForPostAtIndex:index] ];<br />  postTextView.text = [dataSource textForPostAtIndex:index];<br />}<br />...<br />@end
    
    Voilà  pour le principe, du moins tel que je le vois ;)
  • muqaddarmuqaddar Administrateur
    13:20 modifié #11
    En fait, hier soir, j'avais un truc qui marchait bien, même avec le segmentedControl, mais sans utiliser le datasource, ni un protocole.

    Alors j'en ai cassé une partie pour suivre tes consignes qui m'ont l'air plus "cocoa friendly".

    Globalement, tu as compris ce que je voulais, même si les 2 tableView (topics et messages) sont au même niveau, et pushent vers la même vue détaillée, dont le datasource peut donc être soit les topics, soit les messages.

    Maintenant ça bugue un peu, et je suis allé relire quelques discussions sur ce site sur les protocoles pour me rafraà®chir la mémoire.

    Voilà  le code d'interface de TopicsTableViewControllers où tout se passe bien.

    #import &lt;UIKit/UIKit.h&gt;<br /><br />@interface TopicsTableViewController : UITableViewController {<br />	<br />	UITableView *topicsTable;<br />	NSArray *items;	<br />	CGSize cellSize;<br />	<br />}<br /><br />@property (nonatomic, retain) IBOutlet UITableView *topicsTable;<br /><br />@property (nonatomic, retain) NSArray *items;<br /><br />@end<br /><br />// protocole qui sera implémenté par le datasource récupéré dans contentViewController<br />@protocol ItemsViewDataSource<br />- (NSDictionary*)itemAtIndex:(NSUInteger)index;<br />@end
    


    Note que je préfère une méthode qui va chercher l'item (le dico) plutôt que chaque propriété. Le protocole s'appelle ItemsViewDataSource plutôt que PostViewDataSource tout simplement parce qu'il peut s'agir du datasource de topics ou de messages.

    Maintenant, le code d'interface et d'implémentation de contentViewController. C'est bien lui qui doit implémenter la méthode du protocole non ?

    #import &lt;UIKit/UIKit.h&gt;<br />#import &quot;TopicsTableViewController.h&quot;<br /><br />@interface ContentViewController : UIViewController {<br />	<br />	UISegmentedControl *navigationSegmentedControl;<br />	<br />	UILabel *titleLabel;<br />	UIWebView *contentWebView;<br />	UITextView *categoryTextView, *dateTextView;<br /><br />	NSDictionary *item;<br />	NSUInteger itemIndex;<br />	<br />	id&lt;ItemsViewDataSource&gt; dataSource;<br /><br />}<br /><br />@property (nonatomic,retain) IBOutlet UISegmentedControl *navigationSegmentedControl;<br /><br />@property (nonatomic,retain) NSDictionary *item;<br />@property (nonatomic) NSUInteger itemIndex;<br /><br />@property(nonatomic, assign) id&lt;ItemsViewDataSource&gt; dataSource;<br /><br />- (void)reloadData;<br /><br />- (IBAction)fastRewind:(id)sender;<br />- (IBAction)segmentedControlAction:(id)sender;<br /><br />@end
    



    #import &quot;ContentViewController.h&quot;<br /><br />@implementation ContentViewController<br /><br />@synthesize navigationSegmentedControl, titleLabel, contentWebView, categoryTextView, dateTextView;<br />@synthesize dataSource, item, items, itemIndex;<br /><br />-(void)setItemIndex:(NSUInteger)index<br />{<br />&nbsp; itemIndex = index;<br />&nbsp; [self reloadData];<br />}<br /><br />-(void)setDataSource:(id&lt;ItemsViewDataSource&gt;)obj<br />{<br />&nbsp; dataSource = obj;<br />&nbsp; [self reloadData];<br />}<br /><br />- (void)viewDidLoad {<br />	[super viewDidLoad];	<br />	// fill the view with data<br />	[self reloadData];<br />}<br /><br />- (void)reloadData {<br />	<br />	item = [dataSource itemAtIndex:itemIndex];<br /><br />	NSString *titleString = [NSString stringWithString:[item valueForKey:@&quot;title&quot;]];<br />	NSString *linkString = [NSString stringWithString:[item valueForKey:@&quot;link&quot;]];<br />	NSString *descriptionString = [NSString stringWithString:[item valueForKey:@&quot;description&quot;]];<br />	NSString *categoryString = [NSString stringWithString:[item valueForKey:@&quot;category&quot;]];<br />	NSString *dateString = [NSString stringWithString:[item valueForKey:@&quot;date&quot;]];<br /><br />&nbsp; &nbsp; &nbsp;  ...etc.<br />}
    


    Déjà  si tu redéclares :
    -(void)setItemIndex:(NSUInteger)index
    

    et
    -(void)setDataSource:(id&lt;ItemsViewDataSource&gt;)obj
    

    c'est pour rajouter le reloadData je pense, puisque ces 2 méthodes sont sensées être implémentées par défaut avec le synthetize.

    Ensuite, je pensais que c'était contentViewController qui devait implémenter la méthode du protocole ItemsViewDataSource or TopicsTableViewController me la réclame en warning après cette ligne :

    contentViewController.dataSource = self;
    


    class TopicsTableViewController does not implement the ItemsViewDataSource protocol


    Donc je n'ai pas saisi où implémenter la méthode du protocole...





  • AliGatorAliGator Membre, Modérateur
    13:20 modifié #12
    dans 1239962177:
    Maintenant, le code d'interface et d'implémentation de contentViewController. C'est bien lui qui doit implémenter la méthode du protocole non ?
    Alors en réalité non, mais c'est juste une question de terme/vocabulaire (car vu ton code, tu as bien fait les choses quand même) : le ContentViewController n'implémente pas le protocole, mais il a une variable d'instance "dataSource" qui elle se conforme au protocole. C'est donc l'objet que tu vas affecter à  ce dataSource qui va implémenter le protocole, et pas ta classe ContentViewController.

    dans 1239962177:
    Déjà  si tu redéclares :
    -(void)setItemIndex:(NSUInteger)index
    

    et
    -(void)setDataSource:(id&lt;ItemsViewDataSource&gt;)obj
    

    c'est pour rajouter le reloadData je pense, puisque ces 2 méthodes sont sensées être implémentées par défaut avec le synthesize.
    Exactement. Si j'avais pas mis ces méthodes, ça aurait marché... mais le changement d'itemIndex n'aurait pas provoqué de rechargement du contenu de ta ContentView automatiquement, c'est pour ça que j'ai réécrit ces 2 méthodes pour remplacer l'implémentation par défaut qu'il m'aurait fait sinon avec le synthesize.

    dans 1239962177:
    Ensuite, je pensais que c'était contentViewController qui devait implémenter la méthode du protocole ItemsViewDataSource or TopicsTableViewController me la réclame en warning après cette ligne :

    contentViewController.dataSource = self;
    
    Comme dit au début de ma réponse : c'est le dataSource qui doit implémenter le protocole de ItemsViewDataSource, pas le ContentViewController. Donc c'est TopicsTableViewController ou MessagesTableViewController (ou en fait les deux, si les deux peuvent être mis en dataSource de ton UIViewController). Puisque c'est eux qui seront les dataSource, donc c'est à  eux que ton ContentViewController va demander les données... en appelant les méthodes du protocole sur ces classes qui seront ton dataSource.
  • muqaddarmuqaddar Administrateur
    13:20 modifié #13
    C'est bon ça marche. :)
    J'ai rajouté une ou deux méthodes de protocoles dont j'ai besoin.

    J'ai aussi bridé mon segmentedControl pour pas qu'il aille chercher des items du datasource qui n'existent pas.

    Maintenant, je cherche à  agir sur la propriété "selected" de chaque bouton du segmentedControl. Or je n'ai trouvé que : setEnabled:forSegmentAtIndex:  dans la doc Apple.

    Qu'est-ce qui correspond à  : setSelected:forSegmentAtIndex: ?
    Je n'ai rien vu non plus dans les classes parentes !

  • AliGatorAliGator Membre, Modérateur
    13:20 modifié #14
    [tt]@property(nonatomic) NSInteger selectedSegmentIndex;[/tt] ;)
Connectez-vous ou Inscrivez-vous pour répondre.