Your cell will show repeated textfield values because you are reusing them and not adjusting the cell details when a cell is now expected to represent a different object.
If you do not want this behaviour (you obviously don't) then you need to set the cell details on your dataSource. Then in cellForRowAtIndexPath() you populate the current cell with the respective object details. Or, which I do not advise, you can alloc init a new cell in cellForRowAtIndexPath() for each item you add. This will use up more memory unnecessarily when you have cells that are not visible on screen.
Here is an example: this was written quickly to only demonstrate dynamically populating cells from a datasource, everything else is not a suggestion.
#import "PeopleTableViewController.h"
//--- Person Class
@interface Person : NSObject<UITextFieldDelegate>
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *surname;
@end
@implementation Person
@end
//---
#define CELL_HEIGHT 80.0f
#define TEXTFIELD_HEIGHT 30.0f
#define TEXTFIELD_WIDTH 120.0f
#define TEXT_FIELD_VERTICAL_MARGIN (CELL_HEIGHT - (TEXTFIELD_HEIGHT*2)) / 3
#define TEXT_FIELD_LEFT_MARGIN 20.0f
//--- Person Cell
@class PersonCell;
@protocol PersonCellTextFieldProtocol <NSObject>
-(void)personCell: (PersonCell*)cell nameTextfieldDidChange: (NSString*)newText;
-(void)personCell: (PersonCell*)cell surnameTextfieldDidChange: (NSString*)newText;
@end
@interface PersonCell : UITableViewCell<UITextFieldDelegate>
@property (nonatomic, strong) UITextField *nameTextField;
@property (nonatomic, strong) UITextField *surnameTextField;
@property (nonatomic, strong) UILabel *positionLabel;
@property (nonatomic, assign) id<PersonCellTextFieldProtocol> delegate;
@end
@implementation PersonCell
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self)
[self setupSubviews];
return self;
}
-(void)setupSubviews
{
NSUInteger nameTextFieldYPosition = TEXT_FIELD_VERTICAL_MARGIN;
self.nameTextField = [[UITextField alloc] initWithFrame: CGRectMake(TEXT_FIELD_LEFT_MARGIN, nameTextFieldYPosition, TEXTFIELD_WIDTH, TEXTFIELD_HEIGHT)];
self.nameTextField.borderStyle = UITextBorderStyleRoundedRect;
self.nameTextField.placeholder = @"Name";
self.nameTextField.delegate = self;
[self.nameTextField addTarget:self action:@selector(nameTextFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
[self.contentView addSubview: self.nameTextField];
self.surnameTextField = [[UITextField alloc] initWithFrame: CGRectMake(TEXT_FIELD_LEFT_MARGIN, CGRectGetMaxY(self.nameTextField.frame) + TEXT_FIELD_VERTICAL_MARGIN, TEXTFIELD_WIDTH, TEXTFIELD_HEIGHT)];
self.surnameTextField.borderStyle = UITextBorderStyleRoundedRect;
self.surnameTextField.placeholder = @"Surname";
self.surnameTextField.delegate = self;
[self.surnameTextField addTarget:self action:@selector(surnameTextFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
[self.contentView addSubview: self.surnameTextField];
self.positionLabel = [[UILabel alloc] initWithFrame: CGRectMake(5, 0, 10, 20)];
self.positionLabel.font = [UIFont systemFontOfSize: 10];
[self.contentView addSubview: self.positionLabel];
self.positionLabel.center = CGPointMake(self.positionLabel.center.x, self.contentView.center.y);
}
-(void)layoutSubviews
{
self.positionLabel.center = CGPointMake(self.positionLabel.center.x, self.contentView.center.y);
}
-(void)nameTextFieldDidChange:(UITextField*)textField
{
if([self.delegate respondsToSelector: @selector(personCell:nameTextfieldDidChange:)])
[self.delegate personCell:self nameTextfieldDidChange:textField.text];
}
-(void)surnameTextFieldDidChange:(UITextField*)textField
{
if([self.delegate respondsToSelector: @selector(personCell:surnameTextfieldDidChange:)])
[self.delegate personCell:self surnameTextfieldDidChange:textField.text];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
@end
//---
@interface PeopleTableViewController ()<PersonCellTextFieldProtocol>
@end
@implementation PeopleTableViewController
{
NSMutableArray *_peopleArray;
}
-(void)viewDidLoad
{
_peopleArray = [[NSMutableArray alloc] init];
[self.tableView reloadData];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
PersonCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier: @"CellWithNameAndSurname"];
if(!cell)
{
cell = [[PersonCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CellWithNameAndSurname"];
cell.contentView.backgroundColor = [[UIColor blueColor] colorWithAlphaComponent: 0.08f];
cell.delegate = self;
}
//this should be outside the above if statement!
Person *respectivePerson = _peopleArray[indexPath.row];
cell.nameTextField.text = respectivePerson.name;
cell.surnameTextField.text = respectivePerson.surname;
cell.positionLabel.text = [NSString stringWithFormat:@"%i", (int)indexPath.row];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return CELL_HEIGHT;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _peopleArray.count;
}
-(void)personCell:(PersonCell *)cell nameTextfieldDidChange:(NSString *)newText
{
Person *respectivePerson = _peopleArray[[self.tableView indexPathForCell: cell].row];
respectivePerson.name = newText;
}
-(void)personCell:(PersonCell *)cell surnameTextfieldDidChange:(NSString *)newText
{
Person *respectivePerson = _peopleArray[[self.tableView indexPathForCell: cell].row];
respectivePerson.surname = newText;
}
- (IBAction)addItemBtnClick:(id)sender
{
Person *newPerson = [Person new];
[_peopleArray addObject: newPerson];
[self.tableView reloadData];
}
@end
When I click add, I get the following table without any repetitions when I scroll:
