UITableView折叠展开后按钮选中状态未正确恢复问题求助
你的核心问题在于单元格复用过程中,按钮状态设置没有作用到正确的Cell上。在cellForRowAtIndexPath里调用setHalfButton:/setFullButton:时,你用[comboTableView cellForRowAtIndexPath:indexPath]获取Cell,但此时当前Cell还处于配置阶段,尚未被添加到TableView的可视区域,这个方法可能返回nil或者不是你正在配置的那个Cell,导致样式设置完全无效。
下面是具体的修复步骤:
1. 重构按钮状态配置方法
将原来依赖NSIndexPath获取Cell的方法,改为直接接收ComboTableViewCell作为参数,这样可以确保操作的是当前正在配置的Cell:
-(void)configureHalfButtonForCell:(ComboTableViewCell*)cell { [cell.halfBtnOutlet setTitleColor:[UIColor colorWithRed:0 green:102.0f/255.0f blue:0 alpha:1] forState:UIControlStateNormal]; [cell.fullBtnOutlet setTitleColor:[UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:1] forState:UIControlStateNormal]; [cell.halfBtnOutlet.titleLabel setFont:[UIFont boldSystemFontOfSize:15.f]]; [cell.fullBtnOutlet.titleLabel setFont:[UIFont systemFontOfSize:15.f]]; } -(void)configureFullButtonForCell:(ComboTableViewCell*)cell { [cell.fullBtnOutlet setTitleColor:[UIColor colorWithRed:0 green:102.0f/255.0f blue:0 alpha:1] forState:UIControlStateNormal]; [cell.halfBtnOutlet.setTitleColor:[UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:1] forState:UIControlStateNormal]; [cell.fullBtnOutlet.titleLabel setFont:[UIFont boldSystemFontOfSize:15.f]]; [cell.halfBtnOutlet.titleLabel setFont:[UIFont systemFontOfSize:15.f]]; }
2. 修复cellForRowAtIndexPath配置逻辑
在Cell配置时,直接传入当前Cell到新的配置方法中,同时增加状态重置步骤,避免Cell复用带来的旧样式残留:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellIdentifier = @"ComboCell"; ComboTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell == nil) { cell = [[ComboTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; // 把按钮Target添加移到这里,避免重复绑定事件(关键优化) [cell.halfBtnOutlet addTarget:self action:@selector(halfBtnClicked:) forControlEvents:UIControlEventTouchUpInside]; [cell.fullBtnOutlet addTarget:self action:@selector(fullBtnClicked:) forControlEvents:UIControlEventTouchUpInside]; } // 先重置所有状态,避免复用旧Cell的残留样式 cell.halfBtnOutlet.hidden = YES; cell.fullBtnOutlet.hidden = YES; cell.accessoryType = UITableViewCellAccessoryNone; if([selectedRowsInSectionDictionary[@(indexPath.section)] containsObject: indexPath]) { cell.accessoryType = UITableViewCellAccessoryCheckmark; cell.halfBtnOutlet.hidden = NO; cell.fullBtnOutlet.hidden = NO; if( comboItemsArray[indexPath.section].allComboItems[indexPath.row].pQuantity == 0.5) { [self configureHalfButtonForCell:cell]; } else { [self configureFullButtonForCell:cell]; } } cell.comboTitle.text = comboItemsArray[indexPath.section].allComboItems[indexPath.row].pName; return cell; }
3. 额外优化:避免重复绑定按钮事件
原来的代码每次配置Cell都给按钮添加Target,会导致同一个按钮被多次绑定相同事件,点击时触发多次响应。上面的修复已经把Target添加移到Cell初始化分支里,确保每个Cell只绑定一次事件。如果你的Cell是从XIB/Storyboard加载的,可以把Target绑定移到Cell的awakeFromNib方法中:
// ComboTableViewCell.m - (void)awakeFromNib { [super awakeFromNib]; [self.halfBtnOutlet addTarget:self.delegate action:@selector(halfBtnClicked:) forControlEvents:UIControlEventTouchUpInside]; [self.fullBtnOutlet addTarget:self.delegate action:@selector(fullBtnClicked:) forControlEvents:UIControlEventTouchUpInside]; }
同时记得给Cell添加一个delegate属性,在ViewController的cellForRowAtIndexPath里设置cell.delegate = self。
这样修改后,当你重新加载Section时,Cell会根据comboItemsArray里保存的pQuantity值,正确渲染按钮的选中状态,不会再出现重置为默认值的问题。
内容的提问来源于stack exchange,提问作者casillas

