UItableView Cell Resuablity Data getting interchaged while scrolling

1.2k Views Asked by At

Grouped TableView with 4 rows in each Section

Hi All,

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

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

        UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 5, 200, 30)];
        textField.tag = 123;
        textField.placeholder = @"Enter Text";
        textField.autocorrectionType = UITextAutocorrectionTypeNo;
        textField.delegate = self;
        [cell.contentView addSubview:textField];

    }

    UITextField *textField = (UITextField *) [cell.contentView viewWithTag:123];
        if (indexPath.row == 0) {
            [textField setPlaceholder:@"Employee ID"];
        }
        else if (indexPath.row == 1)
        {
            [textField setPlaceholder:@"Employee Name"];
        }
        else if (indexPath.row == 2)
        {
            [textField setPlaceholder:@"Employee Phone"];
        }
         if (indexPath.row == 3)
        {
            [textField setPlaceholder:@"Employee Email"];
            UIButton *saveButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            [saveButton setFrame:CGRectMake(200, 0, 100, 40)];
            [saveButton setTitle:@"Save Emp" forState:UIControlStateNormal];
            [saveButton addTarget:self action:@selector(saveEmployeeToCoreData:) forControlEvents:UIControlEventTouchUpInside];
            [saveButton setTag:indexPath.section];
            [cell addSubview:saveButton];
        }

    return cell;
}

Hi Everyone, I am using this piece of code for getting the above output But when i am scrolling the tableview the output i am getting is

when i am scrolling the tableview the output i am getting

And if i enter any text in the section and scrolling the text, then the text is changing in the cells.

8

There are 8 best solutions below

2
On

You need to use the custom UITableViewCell & in that class file, you need to get this tied up in the cell Class file . More importantly, need to maintain the datasource for it .

Don't use the tag as 0. I mean, set something similar for every views

txtView.tag = 25+indexPath.section;

0
On

You are adding a subview to the cell in one of the cases:

[cell addSubview:saveButton];

This subview does NOT get removed when you dequeue an old cell. You have to explicitly remove the subview for those cases. This will cause unexpected behaviour.

I really recommend to subclass UITableViewCell and add the components to that subclass. by doing so, you can hide its saveButton-property for the cases where you do not want a saveButton.

0
On

Change this "textField.tag = 123" to "text.tag = indexPath.row" in all places. It will work properly.

1
On

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

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

     if (cell == nil) {
         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

         UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 5, 200, 30)];
         textField.tag = 123;
         textField.placeholder = @"Enter Text";
         textField.autocorrectionType = UITextAutocorrectionTypeNo;
         textField.delegate = self;
         [cell.contentView addSubview:textField];
    } else {
         //here the cell is reused, so remove the button here
         [[cell.contentView viewWithTag:124] removeFromSuperview];
    }

    UITextField *textField = (UITextField *) [cell.contentView viewWithTag:123];
    if (indexPath.row == 0) {
        [textField setPlaceholder:@"Employee ID"];
    }
    else if (indexPath.row == 1)
    {
        [textField setPlaceholder:@"Employee Name"];
    }
    else if (indexPath.row == 2)
    {
        [textField setPlaceholder:@"Employee Phone"];
    }
     if (indexPath.row == 3)
    {
        [textField setPlaceholder:@"Employee Email"];
        UIButton *saveButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [saveButton setFrame:CGRectMake(200, 0, 100, 40)];
        [saveButton setTag:124];
        [saveButton setTitle:@"Save Emp" forState:UIControlStateNormal];
        [saveButton addTarget:self action:@selector(saveEmployeeToCoreData:) forControlEvents:UIControlEventTouchUpInside];
        //[saveButton setTag:indexPath.section];
        [cell.contentView addSubview:saveButton];
    }

    return cell;

}
2
On

As per your screen shot there are three visible cell. so when ever you load 4th cell ios will give you reference of 1st cell. here you have already set button for employee email. so that it will visible and again you also set employee id and phone.

So when you reuse the cell your logic should like you need to reset the cell to the default case in this example you can remove that button or hide it and then as per the cell info you should set the cell properties.

I hope you understand the problem.

    if (indexPath.row == 3)
                {
                    [textField setPlaceholder:@"Employee Email"]; 
                    UIButton *saveButton = [cell.contentView viewWithTag:124];

                   if(saveButton == nil) 
                         saveButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];


                    [saveButton setFrame:CGRectMake(200, 0, 100, 40)];
                    [saveButton setTag:124];
                    [saveButton setTitle:@"Save Emp" forState:UIControlStateNormal];
                    [saveButton addTarget:self action:@selector(saveEmployeeToCoreData:) forControlEvents:UIControlEventTouchUpInside];
                    //[saveButton setTag:indexPath.section];
                    [cell.contentView addSubview:saveButton];
                }
0
On

Initialize your UITextField and UIButton with tag in

if (cell == nil) 
{
    //Initialize your `UITextField` and `UIButton`
    // also set tag
}

And set frame of UITextField and UIButton at out of if statement. (you can get UITextField and UIButton by its tag) sure its working for you.

0
On

I too had the same problem,try this,

UITableViewCell *cell;

if (cell == nil) {
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

//initialize the tableviewcell outside,

2
On

Try this code it reuse cells in table view

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

        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

            UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 5, 200, 30)];
            textField.tag = 123;
            textField.placeholder = @"Enter Text";
            textField.autocorrectionType = UITextAutocorrectionTypeNo;
            textField.delegate = self;
            [cell.contentView addSubview:textField];

           UIButton *saveButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
           [saveButton setFrame:CGRectMake(200, 0, 100, 40)];
           [saveButton setTitle:@"Save Emp" forState:UIControlStateNormal];
           [saveButton addTarget:self action:@selector(saveEmployeeToCoreData:) forControlEvents:UIControlEventTouchUpInside];
           [saveButton setTag:124];
           [cell.contentView addSubview:saveButton];

        }

        UITextField *textField = (UITextField *) [cell.contentView viewWithTag:123];
        UIButton *saveButton =(UIButton*)[cell.contentView viewWithTag:124];
       saveButton.hidden=YES;
            if (indexPath.row == 0) {
                [textField setPlaceholder:@"Employee ID"];
            }
            else if (indexPath.row == 1)
            {
                [textField setPlaceholder:@"Employee Name"];
            }
            else if (indexPath.row == 2)
            {
                [textField setPlaceholder:@"Employee Phone"];
            }
             if (indexPath.row == 3)
            {
                [textField setPlaceholder:@"Employee Email"];
                saveButton.hidden=NO;
            }

        return cell;
    }