Tableviews cells change after scrolling down

I am making a form inside a grouped table. In this form, I have UIswitches and text fields. But after scrolling, the cell styles change.

Here is my cellForRowAtIndex

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = nil; static NSString *MyIdentifier = @"GenericCell"; cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ; } NSString *text = nil; if(indexPath.section == CREDENTIALS_SECTION){ if (indexPath.row == 0) { NSLog(@"tot hier login"); UITextField *login = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)]; login.adjustsFontSizeToFitWidth = YES; login.placeholder = @" example@gmail.com "; login.keyboardType = UIKeyboardTypeEmailAddress; login.returnKeyType = UIReturnKeyNext; login.backgroundColor = [UIColor clearColor]; login.tag = 0; login.delegate = self; [login setEnabled: YES]; [cell addSubview:login]; }else if (indexPath.row == 1){ NSLog(@"tot hier pass"); UITextField *pass = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)]; pass.adjustsFontSizeToFitWidth = YES; pass.placeholder = @"Required"; pass.keyboardType = UIKeyboardTypeDefault; pass.returnKeyType = UIReturnKeyDone; pass.secureTextEntry = YES; pass.backgroundColor = [UIColor clearColor]; pass.tag = 0; pass.delegate = self; [cell addSubview:pass]; } if (indexPath.row == 0) { // Email text = @"Email"; } else if(indexPath.row == 1) { text = @"Password"; } }else if(indexPath.section == METHODS_SECTION){ UISwitch *toggleSwitch = [[UISwitch alloc]initWithFrame:CGRectMake(220, 10, 100, 30)]; toggleSwitch.tag = indexPath.row; [toggleSwitch addTarget:self action:@selector(toggleSwitched:) forControlEvents:UIControlEventValueChanged]; [cell addSubview:toggleSwitch]; if (indexPath.row == 0) { // Web text = @"Web applicatie"; } else if(indexPath.row == 1) { //Mobile text = @"Mobiele applicatie"; } else if(indexPath.row == 2) { //Mail text = @"E-mail"; } }else if(indexPath.section == PHONE_SECTION){ UITextField *phoneText = [[UITextField alloc] initWithFrame:CGRectMake(20, 10, 185, 30)]; phoneText.adjustsFontSizeToFitWidth = YES; phoneText.font = [UIFont fontWithName:@"Arial-BoldMT" size:18]; phoneText.keyboardType = UIKeyboardTypeNumberPad; phoneText.delegate = self; phoneText.textColor = [UIColor blackColor]; phoneText.text = _person.phone; [cell addSubview:phoneText]; }else if(indexPath.section == REMARK_SECTION){ UITextView *textView = [[UITextView alloc]initWithFrame:CGRectMake(20, 10, 280, 260)]; textView.text = _person.remark; textView.delegate = self; textView.font = [UIFont fontWithName:@"Arial" size:15.0]; textView.backgroundColor = [UIColor clearColor]; [cell addSubview:textView]; text = @""; }else if(indexPath.section == BUTTON_SECTION){ cell.backgroundColor = [UIColor redColor]; text = @"test"; } cell.textLabel.text = text; return cell; } 

After some searching, I found that more people are facing this problem. And that the problem lies in this piece of code.

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = nil; static NSString *MyIdentifier = @"GenericCell"; cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ; } NSString *text = nil; 

But I did not find a solution for this. Hope anyone can help!

Yours faithfully!

Explanation

Oké, so here you see a screenshot of my form. below I have a red cell (save button), when I scroll down, other cells get a red background. And some cells, text property are changing. enter image description here

+4
source share
6 answers

This is not a gong for work. Apparently, you still do not understand how the reuse mechanism works.

What do you do? First you select a cell for reuse. If you get to one level, but the problem will come later. If you do not receive it, you will create a new one.

When you create a new one that starts at the beginning, before the user starts scrolling, you will add some UIItems depending on the section and line. I will explain why this is not really a reasonable thing.

Then the user scrolls. Cells will disappear from the screen and then become available for reuse. You will then receive cells for reuse. But it may well happen that these cells already have additional UI elements, because you used them before. In the next process, you will add new user interface elements regardless of whether there are any additional user interface elements in this cell.

What can you do:

  • Create your own custom subclasses of table cells. One subclass for each set of additional ui elements you may need. This is probably the easiest way to do this. For each subclass, use a different reuse identifier (!!!) This is what I would recommend! However, there are alternatives:

  • You can still live with your concept, but come up with an individual type of identfier reuse for each type of cell that has some kind of extra ui element on it. If so, make sure that these user interface elements are created and added as sub-views in the if (cell == nil) branch of your code. Create them only once, and then reuse them. Cell reuse identifiers can be "email", "electronic input", "password display", "password input", "switch", ...

  • The deviation of the solution above would be to calculate the row and section into the reuse identifier. For example, "cell-id-0.2" for section 0 and line 2 - or so. But still, you will need to make sure that you really reuse the additional UI views and not re-create them every time the cell is filled with data. In addition, the layout in the first section depends on whether you want to enter a password and email or just display them. You still have to deal with these options.

  • If cell == nil is a value, if the cell is reused, first clear it of every user interface element that you may have added earlier. You can do this by tagging your UIViews: let's say 99 - (something other than 0 should do) when creating and reusing it, it lists all the subzones and deletes those that have the 99 tag. Despite this, you can stick with the code, which you have already done.

+3
source

The simplest fix:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"GenericCell"] ; //some more code return cell; } 

This will remove reuse from the tableview, but since it is a limited view, it might be ok. I would still advise taking 1 or 2 of the decisions of Hermann Klecker.

+2
source

If you also need to maintain the state of UIControl, use

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

It will always return your unique table row, and you can use it as needed.

+1
source

Try removing all children from the cell before reusing it. Try the code:

 if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ; } else { [cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; } 
0
source

Remove all subheadings before adding subviews to the cell.

 if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SimpleTableIdentifier]autorelease]; } else { //To remove the subview of cell. for (UIView *vwSubviews in [cell.contentView subviews]) { [vwSubviews removeFromSuperview]; } } 

He can solve your problem.

0
source

In fact, you have bad code.

In mehthod

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

If it is not in if (cell == nil) , you should NOT initialize and use any

 -(void)addSubview:(UIView*)view 

Why?

Cells are views that are reused from a table. So, if you add some subview, the next time you reuse the cell, more subviews will be added on it. They simply overlap and can cause MEMORY LEAK.

Do not forget that the cells are reusable. In this way,

if i have the following code if i don't install the text somewhere else. All cells are expected to have text in their text labels "this is text." Because they are reusable.

 if (someChangingBool) { cell.textLabel.text = @"this is a text"; } 

So I need to have something else for this if it sets the text to something else.

For more information .

0
source

All Articles