2011-02-22 2 views
4

J'essaie de créer une application dans xcode, qui - à côté des autres - lit un flux rss et affiche les messages. Je suis nouveau avec objectif-c et trouve parfois un peu difficile. J'utilise un NSMutableArray pour les histoires récupérées (messages). Chaque histoire est représentée par un NSMutableDictionary qui contient le titre, l'objet, la date et le lien du message. Tout ceci est affiché dans un UITableView dans un UIViewController. J'ai personnalisé ma propre cellule, donc je peux y afficher plusieurs étiquettes. Mon problème est que si j'utilise tableView: heightForRowAtIndexPath :, les 5 premières cellules (qui correspondent à l'écran) s'affichent bien, mais si vous faites défiler vers le bas, les cellules suivantes semblent avoir le même contenu avec le premier 5 (c'est-à-dire les cellules 0 -4 affichage ok, la cellule 5 a le contenu de la cellule 0, la cellule 6 de la cellule 1, etc.)! Si je supprime le tableView: heightForRowAtIndexPath: tout est très bien (sauf ne pas avoir la taille de la cellule que je veux)Objectif C UITableView - Les cellules du tableau affichent un contenu erroné après avoir changé la hauteur de la cellule

Voici comment le code ressemble:

// NavigationContentsViewController.h 
@interface NavigationContentsViewController : 
UIViewController <UITableViewDelegate, UITableViewDataSource> { 

    UITableView *myTableView; 
    IBOutlet UITableView * newsTable; 
    UIActivityIndicatorView * activityIndicator; 
    CGSize cellSize; 
    NSXMLParser * rssParser; 
    NSMutableArray * stories; 
    NSMutableDictionary * item; // it parses through the document, from top to bottom... 

    NSString * currentElement; 
    NSMutableString * currentTitle, * currentDate, * currentSummary, * currentLink; 

} 

@property(nonatomic,retain)NSMutableArray *itemsList; 
@property(nonatomic,retain)UITableView *myTableView; 
- (void)parseXMLFileAtURL: (NSString *)URL; 

.

//NavigationContentsViewController.m 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

// Configure the cell. 
static NSString *MyIdentifier = @"MyIdentifier"; 
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier]; 

if (cell == nil){ 
    cell = [[[CustomCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease]; 
    // Set up the cell 
    int storyIndex = indexPath.row; 
    //[cell setText:[[stories objectAtIndex: storyIndex] objectForKey: @"title"]]; 
    //Story title 
    //cell.textLabel.text = [[stories objectAtIndex: storyIndex] objectForKey: @"title"]; 
    //cell.textLabel.font = [UIFont boldSystemFontOfSize:14]; 
    cell.lTitle.text = [[stories objectAtIndex: storyIndex] objectForKey: @"title"]; 
    cell.lSummary.text = [[stories objectAtIndex: storyIndex] objectForKey: @"summary"]; 
    cell.lDate.text = [[stories objectAtIndex: storyIndex] objectForKey: @"date"]; 

    return cell; 
} 

return cell; 
} 

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

    NSString *selectedCellItem = [NSString stringWithFormat:@"%d", indexPath.row]; 

    TableViewController *fvController = [[TableViewController alloc] initWithNibName:@"TableViewController" bundle:[NSBundle mainBundle]]; 
    fvController.selectedCellItem = selectedCellItem; 
    [self.navigationController pushViewController:fvController animated:YES]; 
    [fvController release]; 
    fvController = nil; 
} 

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 
    return 80; 
} 

Des indices? [EDIT: changed int storyIndex = indexPath.row;]

+1

Pourriez-vous expliquer pourquoi utilisez-vous 'int storyIndex = [indexPath indexAtPosition: [longueur du chemin d'index] - 1];' au lieu de 'int storyIndex = indexPath.row;'? – knuku

+0

S'il y a des sections impliquées, cela devient un peu compliqué ... dans ce cas, je vous recommande de créer plusieurs NSMutableArrays pour chaque section (mais là encore, vous devrez probablement créer un plus grand tableau pour le stocker, ou s'il devient trop gros, vous devrez commencer à charger directement à partir du disque). – FeifanZ

+0

@ NR4TR Tout d'abord merci de m'embêter avec ma question! Comme à écrit, c'est la première fois que je fais face à obj-c, donc il y a plusieurs fois que je pourrais utiliser de mauvaises choses, ou faire des choses d'une manière étrange. Il suffit de lire votre recommandation, et je me suis senti stupide ... Quoi qu'il en soit, cela ne change rien à ma question :) – CrisDeBlonde

Répondre

11

C'est le problème habituel que les gens ont avec la réutilisation des cellules de table.

Cette ligne tente de réutiliser une cellule. cela signifie que si la cellule 0 se déplace au large écran, il sera réutilisé comme cellule 5:

CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier]; 

si une cellule ne peut être réutilisé que vous créez un nouveau:

if (cell == nil){ 
    cell = [[[CustomCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease]; 

et sur la ligne suivante est votre problème, vous configurez la cellule uniquement si une cellule n'a pas pu être réutilisée. Ce qui arrive 5 fois (pour les cellules qui sont visibles lorsque la table devient visible).

Mais toutes les cellules que votre table veut afficher par la suite seront des cellules réutilisées qui ont déjà du contenu.

// Set up the cell 
    /*...*/ 

mais ne vous inquiétez pas. C'est très facile à réparer. Vous devez séparer la création de votre cellule de sa configuration. Juste déplacer autour du code comme ceci:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    static NSString *MyIdentifier = @"MyIdentifier"; 
    CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier]; 

    if (cell == nil){ 
     cell = [[[CustomCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease]; 
    } 
    // whatever happened before. You have a valid cell at this point. 

    // Set up the cell 
    int storyIndex = indexPath.row; 
    //[cell setText:[[stories objectAtIndex: storyIndex] objectForKey: @"title"]]; 
    //Story title 
    //cell.textLabel.text = [[stories objectAtIndex: storyIndex] objectForKey: @"title"]; 
    //cell.textLabel.font = [UIFont boldSystemFontOfSize:14]; 
    cell.lTitle.text = [[stories objectAtIndex: storyIndex] objectForKey: @"title"]; 
    cell.lSummary.text = [[stories objectAtIndex: storyIndex] objectForKey: @"summary"]; 
    cell.lDate.text = [[stories objectAtIndex: storyIndex] objectForKey: @"date"]; 
    return cell; 
} 

EDIT: peut-être que je devrais lire la question la prochaine fois. Mais je suppose que je suis toujours correct à 100%.

Si je supprime le tableView: heightForRowAtIndexPath: tout est très bien (sauf ne pas avoir la taille de la cellule que je veux)

Je pense que c'est une coïncidence. Combien de cellules avez-vous? Je suppose que vers 7 ou 8? Tout va bien parce que toutes vos cellules sont visibles en même temps. Il n'y a donc pas besoin de réutiliser une cellule, et ils ont tous le contenu qu'ils devraient avoir.

+0

Oh mon dieu !!! Tout est comme vous l'avez décrit! Maintenant, cela a du sens. Merci d'avoir donné la solution, ainsi que d'expliquer pourquoi cela devrait être comme ça! – CrisDeBlonde

1

L'utilisation de [indexPath indexAtPosition ...] est probablement votre source d'erreur, car elle n'obtient pas le chemin d'index approprié.

Cependant, si vous créez un CustomCell (espérons-le dans IB?) Alors vous devriez définir la taille de la cellule dans IB, et ne pas le faire dans le code.

+0

a modifié la pièce en utilisant [indexPath indexAtPosition ...] pour int storyIndex = indexPath.row; mais aucun changement n'est arrivé. mais je suis toujours curieux, pourquoi changer la hauteur a à voir avec le contenu des cellules, et si enlever heightForRowAtIndexPath tout va bien. J'ai créé le CustomCell dans xcode et non dans IB. Existe-t-il un autre moyen de définir la hauteur des cellules (maeby dans CustomCell.m)? – CrisDeBlonde

+0

Faites un NSLog sur indexPath.row ... cela devrait fonctionner parfaitement. – FeifanZ

+0

Avez-vous créé le CustomCell en sous-classant UITableViewCell et en ajoutant des étiquettes avec des méthodes comme initWithFrame:? Dans ce cas, définissez la taille de la cellule dans CustomCell.m, car elle ne change pas. – FeifanZ

Questions connexes