Search code examples
iosobjective-cuitableviewcocos2d-iphone

iOS: UItableview repeat values on dequeueReusableCellWithIdentifier


I have a edittext in my cell, When i scroll up or scroll down it sets the 1st cell value to last cell and to the second last cell. I think it is because it dequeue the cell but i am unable to solve this problem. Here is my code for cell:

 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    _myTableView = tableView;
    AddTaskTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"addTaskCell" forIndexPath:indexPath];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    AddTaskDetails *task =[self.tasksArray objectAtIndex:indexPath.row];
    cell.addHours.delegate = self;
    cell.taskDetails.text =task.taskName;
    _hoursTextField = cell.addHours;
    _hoursTextField.delegate = self;
    cell.addHours.tag = indexPath.row;
    cell.addDescriptionBtn.tag = indexPath.row;
    [cell.addDescriptionBtn addTarget:self action:@selector(didTapAddDescButton:) forControlEvents:UIControlEventTouchUpInside];
    [cell.addHours addTarget:self action:@selector(editStart:) forControlEvents:UIControlEventEditingDidBegin];
    [cell.addHours addTarget:self action:@selector(editEnd:) forControlEvents:UIControlEventEditingDidEnd];
    [cell.addHours addTarget:self
                  action:@selector(textFieldDidChange:)
        forControlEvents:UIControlEventEditingChanged];
    if(task.isTextRed)
    {
       cell.taskDetails.textColor = [UIColor colorWithRed:255 green:0 blue:0 alpha:1.0];
        cell.addHours.textColor = [UIColor colorWithRed:255 green:0 blue:0 alpha:1.0];
    }
    else
    {
        cell.taskDetails.textColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1.0];
        cell.addHours.textColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1.0];

    }
    if(task.isBillable)
    {
        cell.backgroundColor = [UIColor whiteColor];
    }
    else
    {
        cell.backgroundColor = [UIColor lightGrayColor];
    }
    AddTaskDetails *task_1 =[self.tasksArray objectAtIndex:indexPath.row];
    if(task_1.hours>0)
    {
        NSString *hours = [[NSString alloc]initWithFormat:@"%d",task_1.hours];
        cell.addHours.text = hours;
    }
    else
    {
        cell.addHours.placeholder = @"0";
    }
    NSString *hours = [[NSString alloc]initWithFormat:@"Total Hours: %ld",_totalHours];
    if(_totalHours<=24)
    {
        _labelTotalHours.text = hours;
    }
    return  cell;
}

This screen shot is with correct values:

Correct Image

In this pic the 4 is incorrect value which is assigned automatically, this value is also not the array.

Wrong Image


Solution

  • Just a short overview, So you get your answer

    UITableView is highly optimized, and thus only keep On-screen visible rows in memory. Now, All rows Cells are cached in Pool and are reused and not regenerated. Whenever, user scrolls the UITableView, it adds the just-hidden rows in Pool and reuses them for next to be visible rows.

    So, now, coming to your answer

    in your method cellForRowAtIndexPath --

    Always reset the values for each index :

    For ex. if you have a UILabel - label in your cell, then while setting it inside cellForRowAtIndexPath, you will need to set the required value for every condition. If you want it to be empty, then set it to ""

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
       if(today){
         label = "today";
       }
       else if(yesterday){
         label = "yesterday";
       }
    else{
       label = ""; **//this is important**
     }
    
    return cell;
    }
    

    ISSUE IN YOUR CODE

    if(task_1.hours>0)
        {
            NSString *hours = [[NSString alloc]initWithFormat:@"%d",task_1.hours];
            cell.addHours.text = hours;
        }
        else
        {
           cell.addHours.text = "";  // YOU NEED TO SET TEXT TO EMPTY AS WELL
            cell.addHours.placeholder = @"0";
        }