[debutant] aide pour détail de tableView

Isa KatIsa Kat Membre
juin 2014 modifié dans Vos applications #1

Bonjour,


 


je sais qu'avant de demander de l'aide sur le forum, il faut avoir fait ses devoirs et j'ai conscience d'être très, très débutante... mais je m'essaie en espérant au moins écrire une question cohérente ;-)


 


J'essaie depuis une semaine de d'intégrer une vue de détail liée aux données d'une tableview.


Touts les livres ou tutos consulté, soit s'arrete après la tableview (et en tableview contrôler) soit sont d'une version trop ancienne pour fonctionner. Je me suis procurer un modèle qui fonctionne, qui correspond a ce que j'ai besoin... mais il utiles des nib et j'arrive pas a appliquer en contexte storyboard pour être en mesure de faire la suite de l'application selon mes besoins.


 


J'essaie de me retrouver dans la documentation de apple, ...e t je m'y perd carrément.


 


voile ou j'en suis rendu:


 


J'ai ma tableview fonctionnelle, les données provenant d'un array dans le ViewController.m (déjà  je me demande si je serai pas mieux de le mettre dans une classe a part, mais c'est pas ma question principale ici) 


 


Je creer un autre ViewController, je creer une classe DetailViewController, je fais un segue entre la cellule et cette vue.


 


Je vois dans la documentation de apple un code pour définir le segue pour "passing data to a destination view controller" .... mais je comprend pas ou je dois mettre ce code!


 


bon, y'a bien d'autre chose que je comprend pas, mais deja si j'arrivais a situer ce bout, je pense que j'avancerais.


 


de la documentation sur le sujet serait aussi apprécié ;-)


«1

Réponses

  • Peux-tu être un petit plus précise ? En particulier, de quel code parles tu ? Peux-tu poster le code que tu cherches à  positionner, et ton code existant ? Cela permettra de t'aider un peu mieux... ;)


  • Isa KatIsa Kat Membre
    juin 2014 modifié #3

    Bonjour Alf, 


     


    voici ce que j'Ai trouvé dans la documentation de Apple, :


    Listing 3-1  Passing data to a destination view controller


    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([[segue identifier] isEqualToString:@ShowDetails]) { MyDetailViewController *detailViewController = [segue destinationViewController]; NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; detailViewController.data = [self.dataController objectInListAtIndex:indexPath.row]; } }

    je suppose, mais j'en suis pas sur, que je dois l'inclure.


     


    mon code... ben lequel justement? Celui de ViewControler.m? ... je mets celui-la...:


     


    #import "ViewController.h"


    #import "CustomCellTableViewCell.h"


     


    @interface ViewController ()


    {


        NSArray*MyArray;


    }


     


    @end


     


    @implementation ViewController


     


    - (void)viewDidLoad


    {


        [super viewDidLoad];


    // Do any additional setup after loading the view, typically from a nib.


        


        self.myTableView.delegate = self;


        self.myTableView.dataSource = self;


        


        MyArray = [[NSArray alloc] initWithObjects:@un,@deux,@trois, nil];


    }


     


    - (void)didReceiveMemoryWarning


    {


        [super didReceiveMemoryWarning];


        // Dispose of any resources that can be recreated.


    }


     


    - (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView


    {


        return 1;


    }


     


    - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section


    {


        return MyArray.count;


    }


     


    - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath


    {


        static NSString *CellIdentifier = @MyCell;


        CustomCellTableViewCell *Cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];


        if(!Cell)


        {


            Cell = [[CustomCellTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];


        }


        


        Cell.MyLabel.text = [MyArray objectAtIndex:indexPath.row];


       


        


        return Cell;


        


    }


     


    @end


  • ho j'avance!


     


    j'ai trouve un exemple ou j'ai pu voir que c'a allait bien a la fin du ViewController.m.


    ok, il reste a tout ajuster car pour le moment mon appui plante, mais j'ai espoir de trouver ou ;-)'


     


    après je me mettrait a la tache d'apprivoiser les Array un peu plus pour avoir plus d'un item par range.


  • Isa KatIsa Kat Membre
    juin 2014 modifié #5

    he ben non, j'arrive pas a deboguer, du moins jusqu'au bout. L'appui s'ouvre maintenant, le tableView s'affiche, tout est beau jusqu'a ce que je clique sur une cellule.


     


    j'a ai vu dans les note que le code sur le segue pourrait aussi être a mettre dans le detailViewController.m, donc je revis au point de e matin: je sais pas ou le mettre, mais en plus, je ne comprend pas le dernier élément que je dois y mettre.


     


    mon code viewController.m est actuellement 


    #import "ViewController.h"


    #import "CustomCellTableViewCell.h"


    #import "DetailViewController.h"


     


    @interface ViewController ()


    {


        NSArray*MyArray;


    }


     


    @end


     


    @implementation ViewController


     


    - (void)viewDidLoad


    {


        [super viewDidLoad];


    // Do any additional setup after loading the view, typically from a nib.


        


        self.myTableView.delegate = self;


        self.myTableView.dataSource = self;


        


        MyArray = [[NSArray alloc] initWithObjects:@un,@deux,@trois, nil];


    }


     


    - (void)didReceiveMemoryWarning


    {


        [super didReceiveMemoryWarning];


        // Dispose of any resources that can be recreated.


    }


     


    - (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView


    {


        return 1;


    }


     


    - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section


    {


        return MyArray.count;


    }


     


    - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath


    {


        static NSString *CellIdentifier = @MyCell;


        CustomCellTableViewCell *Cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];


        if(!Cell)


        {


            Cell = [[CustomCellTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];


        }


        


        Cell.MyLabel.text = [MyArray objectAtIndex:indexPath.row];


        


        


        return Cell;


        


    }


    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender


    {


        if ([[segue identifier] isEqualToString:@showDetail]) {


            NSIndexPath *indexPath = [self.myTableView indexPathForSelectedRow];


            NSDate *object = MyArray[indexPath.row];


    ERREUR SUR CETTE LIGNE en turquoise        [[segue destinationViewController] setDetailItem:object];


        }


    }


     


    /*


     // version d'un appli base sur modele master/detail:


     - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender


    {


        if ([[segue identifier] isEqualToString:@ShowDetails]) {


            DetailViewController *detailViewController = [segue destinationViewController];


            NSIndexPath *indexPath = [self.myTableView indexPathForSelectedRow];


            detailViewController.data = [self.detailItem objectInListAtIndex:indexPath.row];


        }


    }


    */


    /*- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath


    {


        if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {


            NSDate *object = MyArray[indexPath.row];


            self.detailViewController.detailItem = object;


        }


    }


    */


     


     


     


     


    @end


  • Alf1996Alf1996 Membre
    juin 2014 modifié #6

    1. Essayes de mettre des balises "code" lorsque tu joins du code, ce sera plus lisible.


    2. Attention aux conventions de nommage (première lettre en majuscule pour les classes, et en minuscule pour les instances). Ex :

    pour ton array, mets plutôt "NSArray*myArray;"


    3. la méthode prepareForSegue doit effectivement être mise dans ViewController.m ; l'emplacement (début/fin) a peu d'importance. Tu le mets ou tu veux, c'est juste une question de lisibilité.


    4. Dans ton storyboard, tu dois bien avoir le segue avec le même nom que dans ton test du prepareForSegue (ici showDetail, attention aux minuscules/majuscules)


    5. Pour l'erreur, çà  me parait normal, car tu n'as pas des dates mais des NSString dans ton array ; essaye ceci :



    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    if ([[segue identifier] isEqualToString:@showDetail]) {
    NSIndexPath *indexPath = [self.myTableView indexPathForSelectedRow];
    NSString *object = [myArray objectAtIndex:indexPath.row];
    [[segue destinationViewController] setDetailItem:object];
    }
    }

  • Merci Alf, 


    je n'Ai plus de message d'erreur dans le code du segue.


    par contre mon appui bug encore ;-) selon le lot de deboguage, le problème est dans le DetialViewController maintenant, ouf, j'ai encore beaucoup de travail, moi qui pensant avoir un tout petit projet tout simple ;-)


     


    Qu'est ce que tu veux dire pas mettre des balises "code" quand je joins du code ? <code> ?? (il me semble qu'en HTML, balise c'est < >) et a mettre la ou j'ajoute des bouts ?


     


    ok pour les minuscules, ce qui est bon signe pour ma compréhension, c'est que j'avais été étonnée de voir une majuscule la dans le tuto qui m'a aide.  


  • Alf1996Alf1996 Membre
    juin 2014 modifié #8

    Pour mettre les balises code, tu cliques sur le bouton "<>", et tu verras apparaitre une fenêtre dans laquelle tu copies ton code, cela permet une meilleure lisibilité à  l'écran. 


     


    Sinon, pour ton debogage, quel message d'erreur as tu ? ou quel comportement ?


    Car évidemment, dans le DetailViewController, il faut que tu affiches l'objet qui a été sélectionné dans le MasterViewController...


     


    Edit : Ne t'inquiètes pas, c'est normal, même pour un petit projet de patauger au départ. Ce qui est important, c'est d'en profiter pour acquérir les bases proprement. Donc, ne pas hésiter à  poster le code que tu essayes, même si celui ci ne te parait pas très joli ! Le ridicule ne tue pas !


  • Merci autant de tes réponses que de tes encouragements Alf :-)


     


    Bon j'essaie de me recomprendre dans mon code, car, hier, en essayant plein de chose, j'ai fini pas y ajouter des bouts pris ailleurs et la j'ai du mal a m'y retrouver .... bref, j'ai du mal a clarifier quel est l'objet en question, sélectionner dans mon ViewController.m (et pas dans un MasterViewControler) et que je dois afficher dans DetailViewContrioller. Je pensais que c'était mon detalItem mais ça ne semble pas être ça...  


    je fais une peu de ménage dans tous cela, puis je posterai mon code.


  • KubernanKubernan Membre
    juin 2014 modifié #10

    Bonjour,


     


    Alors effectivement comme te l'a dit Alf, tu travailles avec un array de NSString :



    MyArray = [[NSArray alloc] initWithObjects:@un,@deux,@trois, nil];

    Et puis, curieusement tu décides que ton array contient des NSDate :



    NSDate *object = MyArray[indexPath.row];

    Dernière petite chose : tu sembles travailler avec Storyboard. De fait cette partie de code :



    if(!Cell)
    {
    Cell = [[CustomCellTableViewCell alloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:CellIdentifier];
    }

    n'est pas utile. Ta cell ne sera jamais à  nil.


  • AliGatorAliGator Membre, Modérateur
    juin 2014 modifié #11
    Je confirme qu'il faut que tu t'habitudes tout de suite à  respecter les conventions de nommage, ça paraà®t pas comme ça mais c'est vachement important, et autant t'y mettre dès le début plutôt que prendre les mauvaises habitudes ;)
     

    Dernière petite chose : tu sembles travailler avec Storyboard. De fait cette partie de code :

    if(!Cell)
    {
    Cell = [[CustomCellTableViewCell alloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:CellIdentifier];
    }
    n'est pas utile. Ta cell ne sera jamais à  nil.

    Ce n'est pas du tout une question de Storyboard ou pas Storyboard.

    Ca dépend de la méthode utilisée pour demander une cellule recyclée, l'ancienne méthode ou la plus moderne.
    • au début dans les anciens SDK on n'avait que "dequeueReusableCellWithIdentifier:" donc on utilisait celle-là , qui comme le précise la doc retourne une cellule recyclée s'il y en a une de dispo... ou retourne nil s'il n'y en a pas (et du coup c'est à  toi de la créer, d'où la construction typique "if (!cell) { cell = [[... alloc] initWithStyle:... reuseIdentifier:...]; ... }"
    • mais maintenant cette façon de faire est un peu obsolète et on préfère utiliser "dequeueReusableCellWithIdentifier:forIndexPath:", qui " encore une fois comme la doc l'indique " cette fois te retourne une cellule recyclée s'il y en a une dispo, et... t'en crée une nouvelle s'il n'y en a pas (donc du coup t'arrives jamais dans un cas où ça retourne nil en effet, et du coup plus besoin de la construction "if (!cell) ...")
  • Quand tu auras digéré le pavé (très instructif comme toujours) d'AliGator, tu pourras te replonger dans ton DetailViewController. 


    Tu dois avoir une propriété detailItem, qui doit être de type NSString (puisque tu as dans ton prepareForSegue, setDetailItem:object, avec object de type NSString), et qui va contenir ce qui a été sélectionné dans ton ViewController.


    Pour l'afficher, tu dois le faire généralement dans le viewDidLoad, et tu peux par exemple l'afficher dans un UITextField ou un UILabel, de ton DetailViewController ; çà  devrait donner un truc du genre :



    -(void)viewDidLoad {
    [super viewDidLoad];
    self.myLabel.text=self.detailItem;
    }

    où myLabel est un UILabel de ton DetailViewController (attention de bien connecter l'IBOutlet).


     


    Voilà , n'hésites pas à  demander si tu as encore besoin...


  • Re-bonjour,


     


    merci de vos commentaires a tous, ça encourage de plus être seule!


     


    D'abord, pour le passe de date a string, j'avais fait un essaie en recopiant le version de preparerForSegue pris dans ce que génère Xcode quand on demande une base de type Master/details ... et je n'avais pas réalisée qu'il y était question de date! Mais a la base, si j'ai essaye ce code a la place de ce que je voyait de la documentation de Apple, c'est parce que je n'arrivais a a identifier les éléments d'une écriture pointée, et j'avais mélangé les deux versions de codes par al suite.  ce matin j'ai fini pas m'y retrouver sur ce point, j'ai remis le code venant de la documentation, avec les bons éléments aux bonnes places, je pense. 


     


    Pour la modernisation de l'innitialisation des cellules, sans nil, je trouve super intéressant les explications que tu donnes Ali, mais je n'ai pas réussi a la appliquer! Je pense que je n'Ai pas assez de compréhension des arrays pour cela, actuellement je focuse sur le DetailViewController, ensuite je me plongerai dans les arrays... s'aurais sûrement été plus logique de faire l'inverse ;-)


     


    Alf, tu m'éclaire beaucoup, ça avance,mais ça bogue encore.


    c'est une erreur de type SIGABRT


    ​quand je met un breakpoint, le début du lot d'erreur comporte:


    *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<DetailViewController 0x8f91410>


    ​... mais le message est beaucoup, beaucoup plus long.


     


    j'ai fais du ménage dans mon code, et mis des commentaires pour m'y retrouver car je suis loin d'avoir tout mémoriser suffisamment.


     


    actuellement voici mes deux fichier, ViewController.m et DetailViewController.m



    #import "ViewController.h"
    #import "CustomCellTableViewCell.h"
    #import "DetailViewController.h"

    @interface ViewController ()
    {
    NSArray*myArray;
    // le array declare ici, ainsi il sera accessible dans toutes les methodes de la classe, il est defini plus bas
    // est-ce que je serais mieux de le mettre dans un classe a lui, pour qu'il soit accesible dans d'autre classe ?
    }

    @end

    @implementation ViewController

    - (void)viewDidLoad
    {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    self.myTableView.delegate = self;
    self.myTableView.dataSource = self;
    // referre a myTableView que j'ai declaree par glisse du tableView dans le .h

    myArray = [[NSArray alloc] initWithObjects:@un,@deux,@trois, nil];
    // Array est un tableau de variable
    // il faut d'abord le declarer dans le @interface
    // ici, on l'innitialise
    // le methode initWithObjets me permet de mettre des donnees manuellement
    }

    - (void)didReceiveMemoryWarning
    {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

    // ci-dessous, appel de plusieurs methodes propres au TableView
    - (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
    {
    return 1;
    // permet de connaitre le nombre de section. ici 1.
    }

    - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
    return myArray.count;
    // permet de connaitre le nombre de row par section
    // retourne une valeur qui est le nombre de rangees comptees
    }

    - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    // permet de definir notre cellule
    {
    static NSString *CellIdentifier = @myCell;
    CustomCellTableViewCell *Cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    // c'est ici qu'on innitialise la cellule
    if(!Cell) // verifie si la cellule existe, sinon la creer
    {
    Cell = [[CustomCellTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    // la cellule est creer avec le style Default
    /*
    // essaie de moderniser, en eliminant le if(!Cell), grace a dequeueReusableCellWithIdentifier:forIndexPath sugeree par Ali
    static NSString *CellIdentifier = @myCell;
    CustomCellTableViewCell *Cell = [tableView dequeueReusableCellWithIdentifier:forIndexPath::CellIdentifier];
    // c'est ici qu'on innitialise la cellule

    {
    Cell = [[CustomCellTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    // la cellule est creer avec le style Default
    */
    }


    Cell.myLabel.text = [myArray objectAtIndex:indexPath.row];
    // myLabel = label qui se situe dans la cellule et qui va contenir du text
    // pour chaque vaeleur du Array, une cellule va etre creer et afficher valeur.

    return Cell;

    }
    // code pour le segue:

    // version venant de documentation Apple
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
    if ([[segue identifier] isEqualToString:@showDetails]) {
    DetailViewController *detailViewController = [segue destinationViewController];
    NSIndexPath *indexPath = [self.myTableView indexPathForSelectedRow];
    detailViewController.detailItemLabel = [myArray objectAtIndex:indexPath.row];

    // derniere ligne, version d'origine dans aide Apple:[self.detailItem objectInListAtIndex:indexPath.row];
    }
    }



    #import "DetailViewController.h"

    @interface DetailViewController ()
    // dans MAster/detail: - (void)configureView;
    @end

    @implementation DetailViewController

    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
    // Custom initialization
    }
    return self;
    }

    /*


    #pragma mark - Managing the detail item

    //code pris dans appli master/detail
    - (void)setDetailItem:(id)newDetailItem
    {
    if (_detailItemLabel != newDetailItem) {
    _detailItemLabel = newDetailItem;

    // Update the view.
    [self configureView];
    }
    }


    - (void)configureView
    {
    // Update the user interface for the detail item.

    if (self.detailItemLabel) {
    self.detailDescriptionLabel.text = [self.detailItemLabel description];
    }
    }
    */
    - (void)viewDidLoad
    {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    // pris dans version master/detail : [self configureView];
    // ou version dans Audio player: self.title = @Ambient Sound;
    // version de Alf, ajustee a ce que j'ai declaree:
    self.detailItemLabel.text=self.detailItem;
    }

    - (void)didReceiveMemoryWarning
    {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }
    #pragma mark - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    /*
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {

    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
    if ([[segue identifier] isEqualToString:@showDetail]) {
    [[segue destinationViewController] setDetailItem:object];
    }

    }*/
    @end

    la je travail a voir si j'ai déclarée correctement mon detailItem...

  • Attention, dans ViewController, dans le prepareForSegue, ce n'est pas detailItemLabel que tu dois renseigner, mais bien detailItem (NSString), car le label n'existe pas encore (la vue n'est pas encore chargée... donc le label non plus). C'est pour çà  qu'on le fait dans le viewDidLoad du DetailViewController...


     


    Sinon, si çà  plante encore, peux tu mettre tout le message d'erreur ?


  • Ha la ça m'interresse fort ce que tu dis la Alf, 


    moi je ne mettais que des labels ou variables déjà  déclarées!!!!!


     


    ok, je comprend mieux quelque chose qui parle de cela dans un de mes livre, je boss la dessus donc,


    Merci!




  • Je confirme qu'il faut que tu t'habitudes tout de suite à  respecter les conventions de nommage, ça paraà®t pas comme ça mais c'est vachement important, et autant t'y mettre dès le début plutôt que prendre les mauvaises habitudes ;)

     

    Ce n'est pas du tout une question de Storyboard ou pas Storyboard.


    Ca dépend de la méthode utilisée pour demander une cellule recyclée, l'ancienne méthode ou la plus moderne.


    • au début dans les anciens SDK on n'avait que "dequeueReusableCellWithIdentifier:" donc on utilisait celle-là , qui comme le précise la doc retourne une cellule recyclée s'il y en a une de dispo... ou retourne nil s'il n'y en a pas (et du coup c'est à  toi de la créer, d'où la construction typique "if (!cell) { cell = [[... alloc] initWithStyle:... reuseIdentifier:...]; ... }"

     




     


    Heuu non. Je me trompe peut-être mais l'automatic cell loading est implicite avec le Storyboard (mais c'est vrai qu'on peut l'utiliser sans le Storyboard). Ce qui fait que la méthode dequeueReusableCellWithIdentifier: ne renverra jamais nil dans son cas.

  • AliGatorAliGator Membre, Modérateur
    Doc?
  • KubernanKubernan Membre
    juin 2014 modifié #18

    Dans la doc de la méthode dequeueReusableCellWithIdentifier :


     


    This method dequeues an existing cell if one is available or creates a new one using the class or nib file you previously registered. If no cell is available for reuse and you did not register a class or nib file, this method returns nil.


     


    Dans le table view programming guide :



    • Because the prototype cell is defined in a storyboard, the dequeueReusableCellWithIdentifier: method always returns a valid cell. You don't need to check the return value against nil and create a cell manually.


  • AliGatorAliGator Membre, Modérateur
    Ben voilà  quand tu veux ;)
  • Usant...  B)


  • Merci Kubernan,

    En passant, j'adore les chien ;-)


    Donc je supprime tout simple le la ligne if (!cell) sans modifierai le reste du code?
  • KubernanKubernan Membre
    juin 2014 modifié #22


    Merci Kubernan,

    En passant, j'adore les chien ;-)


    Donc je supprime tout simple le la ligne if (!cell) sans modifierai le reste du code?




     


    Ouaf !


     


    Toute la condition if (!cell) { ...blablabla...} n'est pas utile (elle sera toujours fausse). Tu peux la supprimer (en espérant que tu aies saisi un peu le pourquoi du comment).


  • Merci, 


    oui je crois biens avoir compris ;-)


    et j'en prend bonne note.




  • Attention, dans ViewController, dans le prepareForSegue, ce n'est pas detailItemLabel que tu dois renseigner, mais bien detailItem (NSString), car le label n'existe pas encore (la vue n'est pas encore chargée... donc le label non plus). C'est pour çà  qu'on le fait dans le viewDidLoad du DetailViewController...


     




     


    Bon...


    Grand merci Alf! 


    tu me fais voir ce que je comprend pas... je le comprend toujours pas mais au moins je vois c'est quoi que je comprend pas (ouf) 


     


    J'ai relu les premiers chapitres de mon livre principal (celui de Michel Martin).


     


    Je vois que mon appli est en train de devenir un beau bordel car je ne distingue plus assez les variable, les méthodes et les objets, ce qui appel quoi et le renvoie à  quoi ;-)


     


    mais le positif, c'est que je pense que je suis à  la charnière de comprendre le principe de l'Objective C avec tout ça ;-)


     


    Bon, dans mon appli, c'est clair que je ne saisi pas les ajustements que je dois faire dans le PrepareForSegue. Alors je vais commencer par vérifier ce que j'en comprend!


     


    J'ai trouvé plusieurs version de ce code.... que je compare entre-deux pour essayer de comprendre, d'Autant que celui dans la documentation de Apple est en écriture pointé.


     


    Alors j'essaie de traduire et commenter, dis moi si je suis dans le champs!



    // version venant de documentation Apple, tel quel.
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    // insertion de la methode prepareForSegue, qui ne retourne rien, deja, je comprend pas pourquoi c'est pas avec des crochets, mais bon, j'ai rien à  modifier la , donc ce bout, je le copie tel quel.
    {
    if ([[segue identifier] isEqualToString:@showDetails])
    // condition qui vérifie qu'on utilise bien le segue " ShowDetails ", ça me semble clair. sauf un point... il y a une majuscule dans ShowDetails!
    {
    // Bon, c'est a partir d'ici que je veux comprendre moins:
    MyDetailViewController *detailViewController = [segue destinationViewController];
    // je comprend: appliquer la méthode destinationViewController a l'objet segue et en affecter la valeur a l'objet detailViewController de la classe MyDetailViewController.
    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
    // appliquer la méthode indexPathForSelectedRow à  l'objet tableView de la classe courante et en affecter la valeur à  l'objet indexPath de la class NSIndexPath.
    detailViewController.data = [self.detailItem objectInListAtIndex:indexPath.row];
    //Et la c'est la ligne que je comprend le moins. Je comprend: appliquer la méthode objectInListAtIndex ... je sais pas si la suite fait partie de la méthode.... à  l'objet détailItem de la class courante et en affecter la valeur à  méthode data de l'objet detailViewController (et ce ne me semble n'avoir aucun sens!)

    // dernière ligne, j'avais changé pour: [myArray objectAtIndex:indexPath.row]; dans ce car j'applique la méthode objectAtIndex.... à  l'objet myArray...

    // et je comprend que, dans ce cas, que je dois mettre en place les objets: " detailViewController ", et vraisemblablement " data " car je doute de ma lecture ;-). Le premier va avec la création de la vue, le second est en lien avec ce qui sera affiché dans le label. Jusque présent, c'est une variable que je créait et non un object... je vois que je mélange parfois les deux!
    }
    }

    Alors, est-ce que je suis dans le champs???

  • LarmeLarme Membre
    juin 2014 modifié #25

    En quelques mots :


    Tu vas appeler à  un moment donné performSegueWithIdentifier.

    Ton app va regardé si tu as une méthode prepareForSegue:sender.

    Si c'est le cas, elle va passer dedans, sinon, elle va effectuer le changement de contrôleur.


     


    Du coup, déclarer prepareForSegue:sender permet de pré-charger des variables du contrôleur qui va apparaà®tre.

    Donc, le premier truc, c'est d'identifier le segue.

    En effet, on peut très bien imager que si j'appuie sur le bouton1, je veuille aller vers le controller1 et si j'appuie sur le bouton2, d'aller vers le controller2.


    D'où la ligne if ([[segue identifier] isEqualToString:@ZzZ]).


    Ici, à  la place de ZzZ, il faut mettre exactement le nom renseigné dans l'interface builder. Donc c'est case sensitive (majuscule, minuscule, etc.)


     


    Ensuite, il faut récupérer le prochain contrôleur : NextControllerClass *nextController = [segue destinationViewController];


    Donc, maintenant que tu as récupérer le prochain contrôleur, il faut faire quelques settings dessus.


    Dès lors, si tu as déclarer les bonnes variables, tu les affectes :


    nextController.myVariable1 = ZzZ;


    Donc, dans le code précédent, tu récupères l'indexPath souhaité (celui sélectionné).

    Et grâce à  ce dernier, connaissant comment tu as construit ta table en fonction des indexPath et de detailsItem, tu set le data du detailViewController.


     


    Et ensuite, le prochain controller apparaà®t.


  • Alf1996Alf1996 Membre
    juin 2014 modifié #26

    Alors, je vais essayer d'être aussi claire que pourrait l'être notre grand maà®tre Ali (là  c'est pas gagné !)


    Le prepareForSegue est la méthode qui est exécutée avant "d'aller ouvrir la vue suivante", elle ne retourne rien, mais tu y affectes des variables de ta future vue :


    - en tout premier, tu testes le segue, car pour ton ViewController, tu peux avoir plusieurs segue différents (ici tu n'as que showDetail, mais tu pourrais avoir d'autres segue)


    - ensuite, tu crées une instance detailViewController, de classe DetailViewController


    - tu dois ensuite renseigner les propriétés de cette nouvelle instance. Par exemple, si tu as sélectionné l'objet numéro 2 de ta liste, tu vas dire à  ta seconde vue, je veux montrer les détails de l'objet numéro 2.


    Dans ton cas, ton modèle est extrêmement simple (un array de NSString), et donc, tu dois avoir une propriété de type NSString dans ta classe DetailViewController, que tu peux appeler comme tu veux, disons, mySelectedObject, qui sera déclarée comme ceci :



    @property (nonatomic,strong) NSString *mySelectedObject;


    Et alors, dans ton prepareForSegue, tu auras :



    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
    // On récupère l'indexPath de l'objet qui a été sélectionné par l'utilisateur (index sélectionné de la tableView)
    detailViewController.mySelectedObject = [self.myArray objectAtIndex:indexPath.row];
    // Et on affecte la propriété qui va bien dans notre nouvelle instance


    Après, dans ta classe MyDetailViewController, tu vas afficher ton objet sélectionné, ici, vu que c'est un simple NSString, il te suffit d'avoir un label, et de le renseigner au début :


     


    dans le viewDidLoad de ton MyDetailViewController :


     


    -(void) viewDidLoad {
        [super viewDidLoad];
        myLabel.text=[NSString stringWithFormat:@l'objet sélectionné est %@",self.mySelectedObject];
    }

     


    C'est vraiment un marteau pilon pour écraser une mouche, mais évidemment, ceci peut s'appliquer à  des objets nettement plus complexes qu'un NSString, et là , cela aura un vrai intérêt.


     


    Edit : bon apparemment Larme a été plus rapide que moi !


  • Merci a tous les deux,


     


    Bon, en vous lisant, il me semble que j'avais a peu près bien compris, en gros c'est ce que je pensais que c'a faisait, 


    et je vois que j'avais mis les bons noms au bonnes place dans mes essaies.... le problème c'est que c'a marche pas ;-) Donc mon (ou mes) erreur est ailleur. 


    ha, dire que Xcode me fais tout ça tout seul si je prend un TableViewController au lieu d'un tableView!!!! faut vraiment que je tienne l'apparence graphique, mais bon, à  la base, je suis infographiste, du moins je l'étais mais je n'en fais plus que pour mes besoin ça moi! Et puis je veux comprendre. 


     


    Bon je reviens a mon appli, 


     


    la deux choses:


    1- quand je met self.myArray (c'est le nom de mon tableau a moi), j'ai message d'erreur disant qu'il n'y a pas de propriété my array de type ViewController... .... est-ce qu'on doit déclarer un array dans l .h? Moi je l'ai juste défini dans le .m (jusqu'à  maintenant, j'avais tout bonnement enlevé le self.)


     


    2- je me demande si je m'y prend de la bonne façon pour créer l'instance ViewController.... en fait j'ai pas ça dans mes livres...  je me suis fier a des tutus vidéos... j'ai créer nouveau fichier C, indiquant DetailViewController sous classe de ViewController.... est-ce que c'est cela que je devais faire?


     


    Alf, tu dis: C'est vraiment un marteau pilon pour écraser une mouche, mais évidemment, ceci peut s'appliquer à  des objets nettement plus complexes qu'un NSString, et là , cela aura un vrai intérêt.


     


    ben oui c'est l'intérêt  j'ai quand même pas l'intention de faire tout cela juste pour lister un, deux trois ;-)  Mais je me suis dis que si je compliquait le array en même temps, j'allais me perdre très certainement, alors je clarifie une chose èa la fois, ensuite je passerai a autre chose qu'un simple tableau de NSString. En fait, c'est destinée a des audio, mais je me donne du temps avant d'aborder ce point là  ;-), pour le moment, si j'Affiche des données string, je vais déjà  être bien contente!. Et quand je vais aborder la manipulation des audio, je vais commencer par les lier a des simple bouton avant de les intégrer dans un tableau et un DetailViewController!. Mais le but, c'est de tout mettre c'a ensemble. 

  • à‰videmment ce n'était pas un reproche... de dire que c'était un marteau pour écraser la mouche !

    Sinon, pour tes erreurs le mieux serait que tu postes ton projet complet, on pourrait mieux t'expliquer ce qui ne va pas....

    Le but n'est pas de te faire le travail hein mais vu que tu tournes en rond depuis un moment... ce serait plus simple de t'aider à  corriger ton projet plutôt que de le faire de A à  Z.
  • Alf, je ne l'ai pas du tout pris comme un reproche, au contraire, que tu comprend bien pourquoi je me donne ce mal pour un si petit tableau ;-)


     


    poster tout le projet? je fais comment??


     


    reste que je pense le refaire de A a Z car je constate que, dans les liste de Outlet, les nom sont resté ceux que j'avais donnés au tout début. Mais la je pense que je reproduis tout le temps les mêmes erreurs.


     


    T'inquiète pas, je compte pas faire faire le travail a ma place, pour ça, j'engagerais un programmeur... et j'essaierais surtout pas de comprendre ce qu'il fais ;-) La ce que je veux, c'est comprendre, pour pouvoir avancer proprement.


  • J'ai bien compris que tu n'attendais pas les bras croisés que ça ce fasse sinon je ne répondrais plus ; de toute façon ça ne servirais à  rien, ton but est bien de comprendre et ici ce qu'il te faut c'est apprendre à  debugguer

    Sinon pour joindre le projet tu zippes le dossier complet et tu le mets comme fichier joint...
  • bon ben, ça implique qu'il y a mon nom et tout, ok, j'assume!


    y'a meme la photo de mon pitou comme test de fond ;-)


     


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