如何解决UITableView中TextField出现幽灵值的问题
UITableView中TextField出现幽灵值的解决方法
问题根源分析
你的代码存在三个核心问题导致幽灵值出现:
- 逻辑顺序错误:
return cell语句放在了初始化逻辑中间,导致后续的if navigatedFromCompetitorDisplayCell赋值代码永远不会执行。 - 错误存储UI控件引用:用
quantityTextFields存储TextField实例,单元格复用后,同一个indexPath会对应不同的TextField实例,旧引用失效后会导致值混乱。 - 复用未恢复正确值:每次复用单元格时直接清空TextField文本,没有从数据源读取用户之前输入的值,滚动时显示错误。
具体修复步骤
1. 替换数据源结构
删除原来的quantityTextFields,改用字典存储物料编码对应的输入值,而非TextField控件:
// 用物料编码作为key,存储用户输入的数量值 private var quantityValues: [String: String] = [:]
2. 修正cellForRowAt方法
调整代码顺序,确保所有初始化逻辑执行,并且从数据源读取正确值显示:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tblView.dequeueReusableCell(withIdentifier: "competitorCell", for: indexPath) as! CompetitorCell let material = selectedMaterials[indexPath.row] // 从数据源读取值,优先级:用户已输入值 > 跳转带来的默认值 > 空字符串 if let savedQuantity = quantityValues[material.value] { cell.quantityTextField.text = savedQuantity } else if navigatedFromCompetitorDisplayCell && material.value == competitorMaterial { cell.quantityTextField.text = String(compSaleQuantity) } else { cell.quantityTextField.text = "" } cell.label.text = material.value cell.quantityTextField.tag = indexPath.row cell.selectionStyle = .none // 先移除旧的监听,避免复用后重复触发 cell.quantityTextField.removeTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged) cell.quantityTextField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged) cell.quantityTextField.delegate = self return cell }
3. 同步TextField输入到数据源
修改textFieldDidChange方法,将用户输入实时存入quantityValues:
@objc func textFieldDidChange(_ textField: UITextField) { let indexPath = IndexPath(row: textField.tag, section: 0) let material = selectedMaterials[indexPath.row] // 保存输入值到数据源 quantityValues[material.value] = textField.text ?? "" }
核心原理
UITableView的单元格复用机制要求UI状态完全由数据源驱动,永远不要依赖UI控件本身存储数据。通过将用户输入的值存在独立的数据源字典中,每次复用单元格时从字典读取对应值,就能彻底避免幽灵值问题。
内容的提问来源于stack exchange,提问作者Varun Sharma
相关产品推荐
相关产品推荐

