I've got a table where the accessoryView button in the cell is replaced by a custom check mark icon. If the time interval for a pair of temperature settings is enabled, the cell row shows a check mark, along with a time, heating and cooling value. If the time is disabled, no check mark, and time displayed in the timefield.text is modified to state: "Disabled". The code works fine when I use reloadData
. However, since I'm updated only one row at a time, that's overkill for the big table that I'm using. I'm trying to use reloadRowsAtIndexPaths:
but I get screen updates that affect not only the cell that was clicked on, but the previous cell that was clicked on. I was using no animations (UITableViewRowAnimationNone
), but changed that to fading animations (UITableViewRowAnimationFade
) to see what was going on. Sure enough, the fading occurs on the desired table row and the undesired table row. Also, the time value for the current cell row appears in the previous cell row time field. Once I stay with clicking on one row, there's no problem with the updates, but once I switch to another row, I have both rows affected the one time. It's like the update method is picking up cruft from somewhere.
I have also tried bracketing the reloadRowsAtIndexPaths:
call with calls to beginUpdates
and endUpdates
, and nothing changes.
Clearly I'm not understanding something fundamental here. What am I doing wrong? Here is the method in question:
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
UIButton *button = (UIButton *)cell.accessoryView;
BOOL checked;
if (intervalDisabled[((indexPath.section * 4) + indexPath.row)] == NO) {
checked = YES;
intervalDisabled[((indexPath.section * 4) + indexPath.row)] = YES;
} else {
checked = NO;
intervalDisabled[((indexPath.section * 4) + indexPath.row)] = NO;
}
UIImage *newImage = (checked) ? [UIImage imageNamed:@"unchecked.png"] : [UIImage imageNamed:@"checked.png"];
[button setBackgroundImage:newImage forState:UIControlStateNormal];
timeField.text = [NSString stringWithFormat:@"%@", [self.dateFormatter stringFromDate:[timeOfDays objectAtIndex:((indexPath.section * 4) + indexPath.row)]]];
//[self.tableView reloadData]; <-- This works fine
NSArray *rowArray = [NSArray arrayWithObject:indexPath];
[self.tableView reloadRowsAtIndexPaths:rowArray withRowAnimation:UITableViewRowAnimationFade];
}
Edit:
OK. Here is code you requested. I hope it helps. I will be glad to post other portions. Sorry, I haven't got the hang for formatting code in this editor yet.
// Customized cell for setpoints
- (UITableViewCell *)setPointsCell:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *temperatureSymbol;
static NSString *kCustomCellID = @"setPointsCellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCustomCellID];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:kCustomCellID] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
}
// Set up the cell.
NSDictionary *dictionary = [listOfRows3 objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:@"Content"];
NSString *cellValue = [array objectAtIndex:indexPath.row];
//Set properties of label and add its text
cell.textLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
cell.textLabel.text = cellValue;
// Add time field
timeField = [[UITextField alloc] init];
timeField.tag = (indexPath.section * 100) + (indexPath.row * 10) + TIME_FIELD;
CGRect frame = CGRectMake(80.0, 6.0, 90.0, 31.0);
timeField.frame = frame;
timeField.borderStyle = UITextBorderStyleRoundedRect;
timeField.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
// timeField.backgroundColor = [UIColor clearColor];
timeField.textAlignment = UITextAlignmentRight;
// Check and handle situation where time interval is disabled
BOOL rowHasCheck;
if (intervalDisabled[((indexPath.section * 4) + indexPath.row)] == NO) {
rowHasCheck = YES;
timeField.text = [NSString stringWithFormat:@"%@", [self.dateFormatter stringFromDate:[timeOfDays objectAtIndex:((indexPath.section * 4) + indexPath.row)]]];
} else {
rowHasCheck = NO;
timeField.text = @"Disabled";
}
UIImage *image = (rowHasCheck) ? [UIImage imageNamed:@"checked.png"] : [UIImage imageNamed:@"unchecked.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect bFrame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
button.frame = bFrame; // match the button's size with the image size
[button setBackgroundImage:image forState:UIControlStateNormal];
// set the button's target to this table view controller so we can interpret touch events and map that to a NSIndexSet
[button addTarget:self action:@selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside];
button.backgroundColor = [UIColor clearColor];
cell.accessoryView = button;
// Override default keyboard handler so we can use a picker instead
timeField.delegate = self;
[cell.contentView addSubview:timeField];
// Set up termperature (F or C) to display
if (temperatureScale == FAHRENHEIT) {
temperatureSymbol = @"F";
} else {
temperatureSymbol = @"C";
}
// Add heating setpoint field
UITextField *heatingSetPointField = [[UITextField alloc] init];
heatingSetPointField.tag = (indexPath.section * 100) + (indexPath.row * 10) + HEATING_FIELD;
frame = CGRectMake(180.0, 6.0, 52.0, 31.0);
heatingSetPointField.frame = frame;
heatingSetPointField.borderStyle = UITextBorderStyleBezel;
heatingSetPointField.backgroundColor = [UIColor colorWithRed:1.0 green:0.2 blue:0.2 alpha:1.0];
heatingSetPointField.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
heatingSetPointField.textAlignment = UITextAlignmentRight;
heatingSetPointField.text = [NSString stringWithFormat:@"%i %@", hSetpoints[((indexPath.section * 4) + indexPath.row)], temperatureSymbol];
// Override default delegate handler
heatingSetPointField.delegate = self;
[cell.contentView addSubview:heatingSetPointField];
// Add cooling setpoint field
UITextField *coolingSetPointField = [[UITextField alloc] init];
coolingSetPointField.tag = (indexPath.section * 100) + (indexPath.row * 10) + COOLING_FIELD;
frame = CGRectMake(240.0, 6.0, 52.0, 31.0);
coolingSetPointField.frame = frame;
coolingSetPointField.borderStyle = UITextBorderStyleBezel;
coolingSetPointField.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
coolingSetPointField.backgroundColor = [UIColor colorWithRed:0.4 green:0.4 blue:1.0 alpha:1.0];
coolingSetPointField.textAlignment = UITextAlignmentRight;
coolingSetPointField.text = [NSString stringWithFormat:@"%i %@", cSetpoints[((indexPath.section * 4) + indexPath.row)], temperatureSymbol];
// Override default delegate handler
coolingSetPointField.delegate = self;
[cell.contentView addSubview:coolingSetPointField];
[timeField release];
[heatingSetPointField release];
[coolingSetPointField release];
return cell;
}