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

Swift动态TableView获取文本框值异常,多Section时数据错乱求解决

问题根源:TableView 的 Cell 复用机制导致的错误

你遇到的问题核心在于**tableView.cellForRow(at:)只能获取当前屏幕可见的 Cell**,而不是所有逻辑上存在的 Cell。

当你的 TableView 有 4 个 Section 共 16 行时,大部分 Cell 其实并没有被实例化——TableView 为了性能优化,只会创建刚好填满屏幕的 Cell 数量。当你滚动时,离开屏幕的 Cell 会被放入复用池,新进入视野的 Cell 会从复用池取出并重新配置内容。这就导致你遍历所有 Section 和 Row 时:

  • 不在屏幕上的 Cell,cellForRow(at:)会返回nil
  • 甚至可能拿到被复用的、属于其他 Section/Row 的 Cell,这就会出现你看到的"Section 1 的值莫名变化"的情况
正确的解决方案:维护数据源数组,而非直接从 Cell 取数

TableView 的设计理念是数据源驱动 UI,你应该始终维护一个和 TableView 结构对应的数据源数组,当用户在 TextField 输入内容时实时更新这个数组,需要获取所有值时直接读取数据源即可,完全不需要遍历 Cell。

步骤 1:定义数据源数组

首先在你的 ViewController 里定义一个二维数组,对应 Section 和 Row 的结构:

// 外层数组对应 Section,内层数组对应每个 Section 的 Row
var tableViewDataSource: [[String]] = []

初始化时根据你的 Section 数量和每个 Section 的 Row 数量填充初始值(比如 4 个 Section,每个 Section 4 行):

// 假设每个 Section 有 4 行
finalSectionNumber = 4
tableViewDataSource = Array(repeating: Array(repeating: "", count: 4), count: finalSectionNumber)

步骤 2:在 Cell 输入时更新数据源

你需要监听 TextField 的输入事件,实时更新数据源。这里推荐用闭包的方式,避免 ViewController 和 Cell 之间的强耦合:

在 Cell 类里定义闭包,监听 TextField 内容变化:

class CellOutlet: UITableViewCell {
    @IBOutlet weak var txtFieldSpecNumb: UITextField!
    var onTextChanged: ((String?) -> Void)?
    
    override func awakeFromNib() {
        super.awakeFromNib()
        txtFieldSpecNumb.addTarget(self, action: #selector(textFieldChanged(_:)), for: .editingChanged)
    }
    
    @objc private func textFieldChanged(_ textField: UITextField) {
        onTextChanged?(textField.text)
    }
}

然后在 cellForRowAt 方法里绑定闭包,同步更新数据源:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "CellOutlet", for: indexPath) as! CellOutlet
    cell.txtFieldSpecNumb.text = tableViewDataSource[indexPath.section][indexPath.row]
    // 绑定闭包,实时更新数据源
    cell.onTextChanged = { [weak self] text in
        guard let self = self else { return }
        self.tableViewDataSource[indexPath.section][indexPath.row] = text ?? ""
    }
    return cell
}

步骤 3:修改 getAllValue 函数读取数据源

现在你只需要直接遍历数据源数组就能拿到所有正确的值:

func getAllValue() { 
    for (sectionIndex, sectionData) in tableViewDataSource.enumerated() { 
        print("section index: \(sectionIndex)") 
        print("final txt field: \(finalSectionNumber)") 
        for (rowIndex, value) in sectionData.enumerated() { 
            print("row index: \(rowIndex)") 
            print(value) 
        } 
    } 
}

这样无论你的 TableView 有多少个 Section 和 Row,都能准确获取所有输入的值,完全不会受到 Cell 复用机制的影响。

内容的提问来源于stack exchange,提问作者Aldo Sugiarto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 09:07:48