Reputation: 101
I have been trying to figure this out for a bit. I create a custom cell in its own xib file. In my view controller I have setup a table view controller with sections. The data that is being pulled into the table View is based off a fetch request controller from some core data that I have. I set up the custom cell in the cellForRowAtIndexPath function. I am creating a label for each cell within this function and populating the label with some data from the managed object. Everything seems ok when I first run. However, when I try to scroll up and down and new cells are reused the data in the labels are placed in the wrong cells. I have seen and heard this has to do with the reuse of cells. However, have not seen much examples on correcting this issue. Below is some of the code I have in my cellForRowAtIndexPath function. Let me know if any other input may be needed. Thanks for any help.
-(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:@"CustomCell"];
/* do this to get unique value per cell due to sections. */
NSInteger indexForCell = indexPath.section * 1000 + indexPath.row + 1;
NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath];
NSString *lastSession = nil;
UILabel *lastSessionLabel = nil;
if(cell == nil) {
lastSession = [managedObject valueForKey:@"last_session"];
[self.tableView registerNib:[UINib nibWithNibName:@"CustomCell"
bundle:[NSBundle mainBundle]]
forCellReuseIdentifier:@"CustomCell"];
self.tableView.backgroundColor = [UIColor clearColor];
cell = [aTableView dequeueReusableCellWithIdentifier:@"CustomCell"];
lastSessionLabel = [[UILabel alloc]initWithFrame:CGRectMake(410,55, 89, 35)];
lastSessionLabel.textAlignment = UITextAlignmentLeft;
lastSessionLabel.tag = indexForCell;
lastSessionLabel.font = [UIFont systemFontOfSize:17];
lastSessionLabel.highlighted = NO;
lastSessionLabel.backgroundColor = [UIColor clearColor];
cell.contentView.tag = indexForCell;
[cell.contentView addSubview:lastSessionLabel];
} else {
lastSessionLabel = (UILabel *)[cell viewWithTag:indexForCell];
}
if (lastSession && lastSession.length) {
lastSessionLabel.text = lastSession;
}
cell.textLabel.text = [NSString stringWithFormat:@"%@%@%@%@", @"Dr. ",
[managedObject valueForKey:@"first_name"],
@" " ,
[managedObject valueForKey:@"last_name"]];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.editingAccessoryType = UITableViewCellAccessoryNone;
return cell;
}
** Revised Code **
Below are the changes to code: in viewDidLoad is the following:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:@"CustomCell"
bundle:[NSBundle mainBundle]]
forCellReuseIdentifier:@"CustomCell"];
self.tableView.backgroundColor = [UIColor clearColor];
}
in -(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:@"CustomCell"];
NSInteger indexForCell = indexPath.section * 1000 + indexPath.row + 1;
NSLog(@"index for cell: %d",indexForCell);
NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath];
NSString *lastSession = [managedObject valueForKey:@"last_session"];
UILabel *lastSessionLabel = nil;
if(cell == nil) {
NSLog(@"Cell is nil! %@", [managedObject valueForKey:@"first_name"]);
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CustomCell"];
self.tableView.backgroundColor = [UIColor clearColor];
}
lastSessionLabel = [[UILabel alloc]initWithFrame:CGRectMake(410,55, 89, 35)];
lastSessionLabel.textAlignment = UITextAlignmentLeft;
lastSessionLabel.tag = indexForCell;
lastSessionLabel.font = [UIFont systemFontOfSize:17];
lastSessionLabel.highlighted = NO;
lastSessionLabel.backgroundColor = [UIColor clearColor];
[cell.contentView addSubview:lastSessionLabel];
/* Appropriate verbiage for nil last session. */
if (lastSession && lastSession.length) {
lastSessionLabel.text = lastSession;
}
return cell;
}
I am still having issues again with the label cell text changing when I scroll for different cells. I read some where about maybe having to use the prepareForReuse function for this.
Upvotes: 0
Views: 1937
Reputation: 4463
You are only fetching lastSession
when you create a new cell. Try putting this line before the if(cell == nil)
statement.
lastSession = [managedObject valueForKey:@"last_session"];
I.e. this:
NSString *lastSession = [managedObject valueForKey:@"last_session"];
in stead of this:
NSString *lastSession = nil;
UPDATE
You are also setting the same tag for two views:
lastSessionLabel.tag = indexForCell;
...
cell.contentView.tag = indexForCell;
Based on your code sample you should only use the first line, i.e. set the tag for the lastSessionLabel
SECOND UPDATE
You should also only call registerNib:
once in your view lifecycle, e.g. in viewDidLoad
, not every time you need a new cell. Furthermore, you should create a new cell if cell == nil
in stead of using dequeueReusableCellWithIdentifier:
. E.g.
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CustomCell"];
Upvotes: 1