I have a UITableView with each cell being broken into several sections with a different label in each section. The table gets populated by an NSArray of NSDictionaries which contain all the data that populates the cell’s labels. This part of the UITableView works great.
The problem arises when I change some of the values in one of the NSDictionaries and then reload the table with the updated NSArray. Normally, when I call [myTableView reloadData]; nothing is updated even though (through debugging) I can see the updated data being processed. But if I change the standard: if (cell == nil) { to if (1) {, in the cellForRowAtIndexPath method, then it works beautifully. I understand why if(1) { works but I do not understand why I cannot reuse the cells and just change the label text.
Why does if (cell == nil) not work? Is it a huge resource drain to re-initialize each cell?
CODE:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = @"myCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: cellIdentifier];
if (/*cell == nil*/1) {
// Initialize Custom Cell
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
//// Background View
cellBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 622, 43)];
[cellBackgroundView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"Images/Library/phase_table_cell.png"]]];
//// Name Label
nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 250, 18)];
[nameLabel setBackgroundColor:[UIColor clearColor]];
[cellBackgroundView addSubview:nameLabel];
//// Percent Complete Label
percentCompleteLabel = [[UILabel alloc] initWithFrame:CGRectMake(300, 10, 30, 18)];
[percentCompleteLabel setBackgroundColor:[UIColor clearColor]];
[percentCompleteLabel setTextAlignment:UITextAlignmentCenter];
[cellBackgroundView addSubview:percentCompleteLabel];
//// Overall Status Label
overallStatusLabel = [[UILabel alloc] initWithFrame:CGRectMake(352, 7, 63, 30)];
[overallStatusLabel setBackgroundColor:[UIColor clearColor]];
[overallStatusLabel setFont:[UIFont boldSystemFontOfSize:12.0]];
[overallStatusLabel setLineBreakMode:UILineBreakModeWordWrap];
[overallStatusLabel setNumberOfLines:2];
[overallStatusLabel setTextAlignment:UITextAlignmentCenter];
[cellBackgroundView addSubview:overallStatusLabel];
//// Finish Date Label
finishDateLabel = [[UILabel alloc] initWithFrame:CGRectMake(425, 10, 55, 18)];
[finishDateLabel setBackgroundColor:[UIColor clearColor]];
[finishDateLabel setTextAlignment:UITextAlignmentCenter];
[finishDateLabel setFont:[UIFont systemFontOfSize:12.0]];
[cellBackgroundView addSubview:finishDateLabel];
//// Overall Weight Label
overallWeightLabel = [[UILabel alloc] initWithFrame:CGRectMake(505, 10, 30, 18)];
[overallWeightLabel setBackgroundColor:[UIColor clearColor]];
[overallWeightLabel setTextAlignment:UITextAlignmentCenter];
[cellBackgroundView addSubview:overallWeightLabel];
//// Green Risk View
greenRiskView = [[UIView alloc] initWithFrame:CGRectMake(557, 4, 61, 10)];
[greenRiskView setBackgroundColor:[UIColor greenColor]];
[greenRiskView setHidden:YES];
[cellBackgroundView addSubview:greenRiskView];
//// Yellow Risk View
yellowRiskView = [[UIView alloc] initWithFrame:CGRectMake(557, 17, 61, 10)];
[yellowRiskView setBackgroundColor:[UIColor yellowColor]];
[yellowRiskView setHidden:YES];
[cellBackgroundView addSubview:yellowRiskView];
//// Red Risk View
redRiskView = [[UIView alloc] initWithFrame:CGRectMake(557, 30, 61, 10)];
[redRiskView setBackgroundColor:[UIColor redColor]];
[redRiskView setHidden:YES];
[cellBackgroundView addSubview:redRiskView];
[cell.contentView addSubview:cellBackgroundView];
}
// Get Current Dictionary
NSDictionary *dictForIndexPath = [self.phaseArray objectAtIndex:[indexPath row]];
// Set Elements
[nameLabel setText:[dictForIndexPath objectForKey:@"name"]];
[percentCompleteLabel setText:[dictForIndexPath objectForKey:@"percentComplete"]];
[overallStatusLabel setText:[dictForIndexPath objectForKey:@"overallStatus"]];
[overallWeightLabel setText:[[NSNumber numberWithInt:[[dictForIndexPath objectForKey:@"overallWeight"] intValue]] stringValue]];
//// Create Finish Date String
NSString *finishDateString = [NSString stringWithFormat:@"%@/%@/%@", [dictForIndexPath objectForKey:@"finishDay"], [dictForIndexPath objectForKey:@"finishMonth"], [dictForIndexPath objectForKey:@"finishYear"]];
[finishDateLabel setText:finishDateString];
//// Pick Risk View
NSString *riskColor = [dictForIndexPath objectForKey:@"riskColor"];
if ([riskColor isEqualToString:@"Green"]) {
[greenRiskView setHidden:NO];
[yellowRiskView setHidden:YES];
[redRiskView setHidden:YES];
} else if ([riskColor isEqualToString:@"Yellow"]) {
[greenRiskView setHidden:YES];
[yellowRiskView setHidden:NO];
[redRiskView setHidden:YES];
} else {
[greenRiskView setHidden:YES];
[yellowRiskView setHidden:YES];
[redRiskView setHidden:NO];
}
return cell;
}
Probably you are assigning the value within the
if(cell==nil)block? Only the initialization should happen within that block. Move the rest out of it. (Post your completecellForRowcode, if you need more help)//edit: now, after you posted your code i see your problem:
you are storing all your labels and views in member variables.. but of course that only happens, when the
if(cell != nil)block is executed. After that, you always access the same single cell (that was assigned last). So you are updating at least one cell 😉To fix your problem, work e.g. with tags to get your corresponding views back from the cell. I will show it for your backgroundView, but you have to do it for all of your views (INSTEAD of the member variables. Remove them.)
and so on..