Reputation: 9064
My Problem: I have a UITableView section that is used to create a list. Each TableViewCell has UITextField in it. When you begin typing the textfield, a new cell is inserted. All of this functionality works perfectly. However, if the user creates many cells, they go off screen and problems occur. Specifically that the cells on top of the section start to get reused. This results in unwanted text in new cells, and the deletion of text in old ones. How might I fix this?
Images of this problem: (in the second image, as I started typing item 6, item 1 appeared below it)
Code to create UITableViewCells:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"AddListInformationCellid";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
// Intialize TableView Cell
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.backgroundColor = [UIColor whiteColor];
// Initialize TextField
// ... code ommitted for brevity
// Custome intializiation per each kind of TextField
if (indexPath.section == 0) {
playerTextField.tag = 0;
playerTextField.placeholder = @"Title";
}
else if (indexPath.section == 1) {
// Here's where the problem starts *********
playerTextField.tag = indexPath.row + 1;
playerTextField.placeholder = @"List Item";
}
[cell.contentView addSubview:playerTextField];
}
return cell;
}
Code to add/delete cells
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSInteger section = [self.tableView indexPathForCell:(UITableViewCell *)textField.superview.superview].section;
NSInteger row = [self.tableView indexPathForCell:(UITableViewCell *)textField.superview.superview].row;
if (section == 0) {
_myList.name = textField.text;
}
else if (section == 1) {
// Delete cell that is no longer used
if ([string isEqualToString:@""]) {
if (textField.text.length == 1) {
if (cellCount > 1) {
cellCount = cellCount - 1;
[self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:row inSection:1]] withRowAnimation:UITableViewRowAnimationAutomatic];
textField.text = @"";
}
}
}
// Add a new cell
if (self.beganEditing) {
if (![string isEqualToString:@""]) {
if (row == [self.tableView numberOfRowsInSection:1] - 1) {
cellCount = cellCount + 1;
[self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:row + 1 inSection:1]] withRowAnimation:UITableViewRowAnimationAutomatic];
self.beganEditing = NO;
}
}
}
}
return YES;
}
Upvotes: 2
Views: 1195
Reputation: 307
I found your problem. But it's a bit hard to say.
Try to think about, when table view is going to present a cell in a row, it will choose a cell in the reuse-queue which has the same type of the one is going to be shown. In other words, table view just knows the type of the reused-cell it choosed and the comment of the cell is recognized by which row is in! So let see your code.
You can know that you only creat one cell with your text when is nil. However, when it is going to be used, the cell with the same type don't know which row he is in and so it don't know what kind of comment it hold and just presented with the its last infromations!!
Here's the solution. Try to save your infos in an array well-organized(Such as: you can back your info by which row its in ), basic on its rows, try to update your cell's comment by which row its in relating to the info-array.
hope it can help:)
Upvotes: 1
Reputation: 2552
As @Bruno said, you need to watch what you put into the initialization of the cell. A good general rule would be to only put universal rules into the cell == nil
conditional. Anything that depends on the position of the cell in the table view needs to go outside this if
statement.
In the code above, you have a comment "Custom initialization per each kind of text field." That's a pretty good indicator that this code needs to go outside the if
statement.
Secondly, you cannot rely on the table view cells to keep your data for you. If you don't already have one, you need to keep an array of strings that represents each entry in the text fields area. Then when asked for a cell by the table view, you can set each text field's text according to its index path outside the cell == nil
conditional.
Check out this answer as well.
Hope this helps!
Upvotes: 4
Reputation: 3874
You bug is on the
if (cell == nil)
part of your code. You're not considering the else
, which is the case when the cell is reused. (The cell is reused, that's why it's appearing on the bottom).
You should make sure that you treat the reuse case (in other words, that you configure your cell accordingly when its reused)
Upvotes: 3