You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TableViewCell中多UITextField滚动时值重复问题求助

解决UITableView滚动时UITextField值重复的问题

你遇到的问题是UITableView的cell复用机制导致的,再加上你用ArrayOfCell存储cell的方式存在错误,才会出现滚动时值重复、计算数据不准确的情况。下面我给你一步步拆解问题和解决方案:

问题根源

  1. Cell复用导致值残留:当UITableView滚动时,滚出屏幕的cell会被放入复用池,新进入屏幕的cell会复用这些旧cell。你没有在cellForRowAt方法中为每个cell设置对应行的TextField值,所以复用的cell会显示之前输入的内容,造成"重复"现象。
  2. 存储cell数组的错误:ArrayOfCell会不断添加复用的cell实例,数组里会有大量重复的cell对象,而且这些cell对应的行索引已经混乱,点击按钮计算时取到的根本不是每行的真实输入值。

正确解决方案

核心思路是把数据和UI分离:用数组存储每行的输入值,和你的化学品数据源一一对应;在cell复用的时候,从数组中取出对应索引的值填充到TextField;监听TextField的输入变化,实时更新数组中的数据;计算时直接遍历数据数组,而不是cell。

第一步:修正ViewController代码

import UIKit
class Density_Price_Calculation_TableView: UIViewController, UITableViewDelegate, UITableViewDataSource {
    @IBOutlet weak var Density_Price_Calculation_TableView: UITableView!
    @IBOutlet weak var Gravity: UILabel!
    @IBOutlet weak var Price: UILabel!
    
    // 初始化数据数组,和化学品数据源长度一致,默认填充空字符串
    private var phrValues = [String]()
    private var densityValues = [String]()
    private var priceValues = [String]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        Density_Price_Calculation_TableView.delegate = self
        Density_Price_Calculation_TableView.dataSource = self
        
        // 初始化数据数组,和化学品数量匹配
        let chemicalCount = Density_Price_Chemicals_MasterData.instance.getChemical_Names().count
        phrValues = Array(repeating: "", count: chemicalCount)
        densityValues = Array(repeating: "", count: chemicalCount)
        priceValues = Array(repeating: "", count: chemicalCount)
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return Density_Price_Chemicals_MasterData.instance.getChemical_Names().count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "density_price_calculation_cell", for: indexPath) as! Density_Price_Calculation_TableViewCell
        let chemical = Density_Price_Chemicals_MasterData.instance.getChemical_Names()[indexPath.row]
        cell.updateViews(chemical_names: chemical)
        
        // 填充对应索引的输入值,解决复用残留问题
        cell.phreditText.text = phrValues[indexPath.row]
        cell.densityeditText.text = densityValues[indexPath.row]
        cell.priceeditText.text = priceValues[indexPath.row]
        
        // 设置tag,方便在TextField代理中找到对应索引
        cell.phreditText.tag = indexPath.row
        cell.densityeditText.tag = indexPath.row + 1000 // 避免tag重复
        cell.priceeditText.tag = indexPath.row + 2000
        
        // 设置TextField的代理,监听输入变化
        cell.phreditText.delegate = self
        cell.densityeditText.delegate = self
        cell.priceeditText.delegate = self
        
        return cell
    }
    
    @IBAction func btn_pressed(_ sender: UIButton) {
        var totalSize = 0.00, gravity = 0.0, price = 0.0
        // 遍历数据数组,而不是cell数组,确保数据准确
        for i in 0..<phrValues.count {
            let tempPhr = Double(phrValues[i]) ?? 0
            let tempDen = Double(densityValues[i]) ?? 0
            let tempPrice = Double(priceValues[i]) ?? 0
            
            totalSize += tempPhr
            if tempPhr != 0 && tempDen != 0 {
                gravity += tempPhr / tempDen
            }
            price += tempPhr * tempPrice
        }
        
        // 处理除以0的情况,避免崩溃
        if totalSize != 0 && gravity != 0 {
            Gravity.text = String(format: "%.3f", totalSize / gravity)
        } else {
            Gravity.text = "0.000"
        }
        
        if totalSize != 0 {
            Price.text = String(format: "%.3f", price / totalSize)
        } else {
            Price.text = "0.000"
        }
    }
}

// 扩展实现UITextFieldDelegate,实时更新数据数组
extension Density_Price_Calculation_TableView: UITextFieldDelegate {
    func textFieldDidEndEditing(_ textField: UITextField) {
        guard let text = textField.text else { return }
        let index: Int
        
        // 根据tag判断是哪个TextField,找到对应行索引
        switch textField.tag {
        case 0..<1000:
            index = textField.tag
            phrValues[index] = text
        case 1000..<2000:
            index = textField.tag - 1000
            densityValues[index] = text
        case 2000..<3000:
            index = textField.tag - 2000
            priceValues[index] = text
        default:
            return
        }
    }
}

第二步:修正TableViewCell代码

不需要存储cell实例,去掉不必要的代码,同时可以优化键盘收起的逻辑:

import UIKit
class Density_Price_Calculation_TableViewCell: UITableViewCell {
    @IBOutlet weak var chemical_name: UILabel!
    @IBOutlet weak var phreditText: UITextField!
    @IBOutlet weak var densityeditText: UITextField!
    @IBOutlet weak var priceeditText: UITextField!
    
    func updateViews(chemical_names:Density_Price_Calculation) {
        chemical_name.text = chemical_names.chemical_name
    }
    
    // 可以把键盘收起的逻辑移到ViewController,或者保持这里也可以
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        phreditText.resignFirstResponder()
        densityeditText.resignFirstResponder()
        priceeditText.resignFirstResponder()
    }
}

关键改进点说明

  • 数据与UI分离:用三个数组分别存储每行的PHR、密度、价格值,和化学品数据源一一对应,彻底摆脱对cell实例的依赖。
  • 解决复用残留:在cellForRowAt中为每个cell填充对应索引的输入值,确保滚动时显示的是当前行的正确数据。
  • 实时更新数据:通过TextField代理监听输入结束事件,实时更新数据数组,保证数据和UI同步。
  • 避免计算错误:计算时直接遍历数据数组,而不是cell数组,确保取到的是每行的真实输入值,不会因为cell复用导致数据混乱。
  • 容错处理:添加了除以0的判断,避免计算时出现崩溃。

内容的提问来源于stack exchange,提问作者Bibhuranjan Bihari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:47:00