Objective C UITableView - Table cells display wrong content after changing cell's height

12,629

Solution 1

This is the usual problem people have with table cell reuse.

this line tries to reuse a cell. this means if cell 0 moves off screen it will be reused as cell 5:

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

if a cell could not be reused you are creating a new one:

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

and on the next line is your problem, you set up the cell only if a cell couldn't be reused. Which happens 5 times (for the cells that are visible when the table becomes visible).

But all the cells that your table wants to display afterwards will be reused cells that have already content.

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

but don't worry. this is very easy to fix. You have to separate the creation of your cell from its configuration. Just shift some code around like this:

- (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: maybe I should read the question next time. But I guess I'm still 100% correct.

If i remove the tableView:heightForRowAtIndexPath: everything is just fine (except not having the cell size i want)

I think this is coincidence. How much cells do you have? I guess around 7 or 8? Everything is fine because all your cells are visible at the same time. So there is no need to reuse a cell, and they all have the content they should have.

Solution 2

Using [indexPath indexAtPosition…] is most likely your source of error—it's not getting your proper index path.

However, if you are creating a CustomCell (hopefully in IB?) then you should set the size of the cell in IB, and not do it in code.

Share:
12,629
CdB
Author by

CdB

Software engineer

Updated on June 04, 2022

Comments

  • CdB
    CdB about 2 years

    I'm trying to build an application in xcode, which -beside others- reads an rss feed and displays the posts. I'm new with objective-c and find it a bit hard sometimes.

    I use an NSMutableArray for the retrieved stories(posts). Each story is represented by an NSMutableDictionary which contains the title, subject, date and link of the post. All these are displayed in a UITableView within a UIViewController. I have customized my own cell, so i can display multiple labels in them.

    My problem is that if i use tableView:heightForRowAtIndexPath:, first 5 cells (that fit to screen) display ok, but if you scroll down, next cells appear to have the same contents with first 5(that is cells 0-4 display ok, cell 5 has contents of cell 0, cell 6 of cell 1 etc)! If i remove the tableView:heightForRowAtIndexPath: everything is just fine (except not having the cell size i want)

    Here's about how the code looks:

    //  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;
    }
    

    Any clues? [EDIT: changed int storyIndex = indexPath.row;]

  • CdB
    CdB over 13 years
    changed the part using [indexPath indexAtPosition…] to int storyIndex = indexPath.row; but no changes happened. but i'm still curious, why changing the height has to do with cell contents, and if removing heightForRowAtIndexPath everything is just fine. I created the CustomCell in xcode and not in IB. Is there any other way that i can set the cells height (maeby in CustomCell.m) ?
  • FeifanZ
    FeifanZ over 13 years
    Did you create the CustomCell by subclassing UITableViewCell and adding labels with methods like initWithFrame:? In that case, set the size of the cell in CustomCell.m, because it's not changing.
  • CdB
    CdB over 13 years
    indexPath.row works fine - as [indexPath indexAtPosition:[indexPath length] - 1] worked too. It's just the contents being wrong when changing height (even if i use indexPath.row) how can i set the size inside the CustomCell.m (which as u said is subclassing UITableViewCell)?
  • FeifanZ
    FeifanZ over 13 years
    Set its frame in the default init; or you can use a proper initWithFrame. Apple's official documentation is actually helpful here; scroll about a third of the way down to where it says "Customizing Cells": developer.apple.com/library/ios/#documentation/UserExperienc‌​e/… Also see this tutorial for adding custom cells in IB: iphone.galloway.me.uk/iphone-sdktutorials/…
  • CdB
    CdB over 13 years
    Oh God!!! Everything is just like you described! Now it makes sense. Thanks for giving the solution, as well as explaining why it should be like this!
  • CdB
    CdB over 13 years
    @Inspire48 Thanks for all your suggestions! All of your comments helped me understand a bit more the table/cells structure and properties. I searched the tutorials based on your comments and understood things a lot better :)
  • FeifanZ
    FeifanZ over 13 years
    You're welcome! Sorry I didn't catch the actual issue—I'm too used to template code to have realized that in effect you just a had a brace too far down…