doubleace3
doubleace3

Reputation: 101

IOS custom cell with labels showing wrong text when cell reused

I have been trying to figure this out for a bit. I create a custom cell in its own xib file. In my view controller I have setup a table view controller with sections. The data that is being pulled into the table View is based off a fetch request controller from some core data that I have. I set up the custom cell in the cellForRowAtIndexPath function. I am creating a label for each cell within this function and populating the label with some data from the managed object. Everything seems ok when I first run. However, when I try to scroll up and down and new cells are reused the data in the labels are placed in the wrong cells. I have seen and heard this has to do with the reuse of cells. However, have not seen much examples on correcting this issue. Below is some of the code I have in my cellForRowAtIndexPath function. Let me know if any other input may be needed. Thanks for any help.

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

    UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:@"CustomCell"];

    /* do this to get unique value per cell due to sections. */
    NSInteger indexForCell = indexPath.section * 1000 + indexPath.row + 1;

    NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath];



    NSString *lastSession = nil;
    UILabel *lastSessionLabel = nil;
    if(cell == nil) {

        lastSession = [managedObject valueForKey:@"last_session"];

        [self.tableView registerNib:[UINib nibWithNibName:@"CustomCell" 
                                                   bundle:[NSBundle mainBundle]] 
             forCellReuseIdentifier:@"CustomCell"];

        self.tableView.backgroundColor = [UIColor clearColor];
        cell = [aTableView dequeueReusableCellWithIdentifier:@"CustomCell"];

        lastSessionLabel = [[UILabel alloc]initWithFrame:CGRectMake(410,55, 89, 35)];
        lastSessionLabel.textAlignment = UITextAlignmentLeft;
        lastSessionLabel.tag = indexForCell;
        lastSessionLabel.font = [UIFont systemFontOfSize:17];
        lastSessionLabel.highlighted = NO;
        lastSessionLabel.backgroundColor = [UIColor clearColor];

        cell.contentView.tag = indexForCell;
        [cell.contentView addSubview:lastSessionLabel];
    } else {
        lastSessionLabel = (UILabel *)[cell viewWithTag:indexForCell];
    }

        if (lastSession && lastSession.length) {        
            lastSessionLabel.text = lastSession;
        } 


    cell.textLabel.text = [NSString stringWithFormat:@"%@%@%@%@", @"Dr. ",
                           [managedObject valueForKey:@"first_name"], 
                           @" " , 
                           [managedObject valueForKey:@"last_name"]];

    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    cell.editingAccessoryType = UITableViewCellAccessoryNone;


    return cell;
}

** Revised Code **

Below are the changes to code: in viewDidLoad is the following:

 - (void)viewDidLoad
{
    [super viewDidLoad];
   [self.tableView registerNib:[UINib nibWithNibName:@"CustomCell" 
                                           bundle:[NSBundle mainBundle]] 
         forCellReuseIdentifier:@"CustomCell"];

       self.tableView.backgroundColor = [UIColor clearColor];
  }     

 in -(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:  (NSIndexPath *)indexPath {
  UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:@"CustomCell"];
    NSInteger indexForCell = indexPath.section * 1000 + indexPath.row + 1;
    NSLog(@"index for cell: %d",indexForCell);

    NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath];


    NSString *lastSession = [managedObject valueForKey:@"last_session"];
 UILabel *lastSessionLabel = nil;
    if(cell == nil) {
        NSLog(@"Cell is nil! %@", [managedObject valueForKey:@"first_name"]);

         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CustomCell"];


        self.tableView.backgroundColor = [UIColor clearColor];
   }    
        lastSessionLabel = [[UILabel alloc]initWithFrame:CGRectMake(410,55, 89, 35)];
        lastSessionLabel.textAlignment = UITextAlignmentLeft;
        lastSessionLabel.tag = indexForCell;
        lastSessionLabel.font = [UIFont systemFontOfSize:17];
        lastSessionLabel.highlighted = NO;
        lastSessionLabel.backgroundColor = [UIColor clearColor];


        [cell.contentView addSubview:lastSessionLabel];
        /* Appropriate verbiage for nil last session. */
       if (lastSession && lastSession.length) {        
            lastSessionLabel.text = lastSession;
        }   
 return cell;  
}

 I am still having issues again with the label cell text changing when I scroll for different cells. I read some where about maybe having to use the prepareForReuse function for this.

Upvotes: 0

Views: 1937

Answers (1)

Paul Hunter
Paul Hunter

Reputation: 4463

You are only fetching lastSession when you create a new cell. Try putting this line before the if(cell == nil) statement.

lastSession = [managedObject valueForKey:@"last_session"];

I.e. this:

NSString *lastSession = [managedObject valueForKey:@"last_session"];

in stead of this:

NSString *lastSession = nil;

UPDATE

You are also setting the same tag for two views:

lastSessionLabel.tag = indexForCell;
...
cell.contentView.tag = indexForCell;

Based on your code sample you should only use the first line, i.e. set the tag for the lastSessionLabel

SECOND UPDATE

You should also only call registerNib: once in your view lifecycle, e.g. in viewDidLoad, not every time you need a new cell. Furthermore, you should create a new cell if cell == nil in stead of using dequeueReusableCellWithIdentifier:. E.g.

cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CustomCell"];

Upvotes: 1

Related Questions