Steaphann Steaphann - 1 year ago 55
Objective-C Question

tableviews cells are changing after scrolling down

I am making a form within a grouped tableview. In this form I have UIswitches and textfields. But after scrolling down, the cells styles are changing.

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 = @"";
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 =;
[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 having this problem. And that the problem lays 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 don't find a solution for it.
Hope anybody can help!

Kind regards!


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

Answer Source

That is not gong to work. Aparently you have not yet fully understand how the re-use mechanism works.

What do you do? First you fetch a cell to be re-used. If you get one -fine so far but the problem comes later. If you don't get one then you create a new one.

When you have created a new one, which is the case at start before the user begins scrolling, then you add some UIItems depending on section and row. I will explain why this is not actually a smart thing to do.

Then the user scrolls. Cells will dissappear from screen and then made available for re-use. Then you will fetch the cells for re-use. But it may well happen that those cells already have additional UI-Items on them because you have used them before in that way. In the following process you will add new UI Items regardless whether there are already additional UI-Items on that very cell.

What can you do:

  1. Create your own custom table cell subclasses. One subclass for each set of additional ui items that you may need. That is probably the neatest way of doing it. For each subclass use a different re-use identifier (!!!) This is what I would recommend! However, there are alternatives:

  2. You could still live with your concept but invent an individual type of re-use identfier for each type of cell that has some type of additional ui item on it. If so, then make sure that these UI items are only created and added as sub-views in the if (cell == nil) branch of your code. Only create them once and then re-use them. Cell reuse-IDs could be "email-display", "email-input" , "password-display", "password-input", "switch", ...

  3. A variance of the solution above would be, to calculate row and section into the reuse-identifier. Such as "cell-id-0.2" for section 0 and row 2 - or so. But still you will have to make sure that you really re-use the additional UI views and do not re-create them every time when the cell is filled with data. Plus, the layout in your first section varies depending on whether you want to input password and e-mail or just display them. You will still have to deal with those variations.

  4. If cell == nil - meaning if a cell is re-used - then first clean it from every UI item that you may have added before. You can do that by tagging your UIViews with - let's say 99 - (anything different from 0 should do) upon creation and when reusing enumerate over all subviews and remove those, which have the tag 99. Despite that you can stick with the code that you have already made.