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

Swift中UITableView添加Section后数据错位问题求助

问题排查与修复方案

嘿,我帮你找出了几个导致section数据混乱的关键错误,咱们一个个拆解并修复:

1. 手动维护numberOfSections完全多余且容易出错

你自己声明了一个numberOfSections变量来控制表格的section数量,但其实每个section对应itemsInTable里的一个元素,直接返回数组的count就行。手动维护这个变量很容易出现同步问题(比如你添加元素后手动加1,但如果后续有删除操作,数组长度和这个变量就会不一致)。

修复代码:
删掉你手动定义的numberOfSections变量,把代理方法改成:

func numberOfSections(in tableView: UITableView) -> Int {
    return itemsInTable.count
}

以后添加元素时,只要往数组里append,然后调用tableView.reloadData()就够了,不用再手动改section数量。

2. Section Header错误使用UITableViewCell重用

这是导致你第1个section数据跑到第4个的核心原因!在viewForHeaderInSection里,你用了dequeueReusableCell来获取header视图——tableView的cell是为表格行设计的,header/footer应该用专门的UITableViewHeaderFooterView。错误重用cell会让旧section的内容被带到新section里,出现数据串位的问题。

修复步骤:

  • 先把Storyboard/XIB里的"SectionCell"改成UITableViewHeaderFooterView(或者用代码自定义一个),设置好对应的identifier(比如"SectionHeader")。
  • 然后修改viewForHeaderInSection方法:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    // 改用专门的HeaderFooterView重用
    let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: "SectionHeader") as! CreationTableHeaderView
    let model = itemsInTable[section]
    
    if model.typeName == "textField" {
        header.Btn.isHidden = true
        header.Txt.isHidden = false
        header.Txt.text = "textField : \(section)"
    } else if model.typeName == "Button" {
        header.Btn.isHidden = false
        header.Txt.isHidden = true
        header.Btn.setTitle("Button \(section)", for: .normal)
        header.Btn.isEnabled = false
        header.Btn.titleLabel?.textColor = .white
        header.Btn.backgroundColor = .black
    }
    return header
}

如果暂时不想改HeaderFooterView,至少要避免重用,直接创建新的cell(但不推荐这么做):

let cell = CreationTableViewCell(style: .default, reuseIdentifier: "SectionCell")

3. cellForRowAt逻辑完全搞反:赋值方向错误

你在cellForRowAt里做了itemsInTable[indexPath.section].content.Hint = cell.txt.text这种操作,这完全搞反了!cellForRowAt的作用是用模型数据配置cell,也就是把模型里的值显示到cell上,而不是反过来把cell的空值(初始时textField的text是空的,placeholder只是提示)赋值给模型。这种错误会导致模型数据被覆盖,cell重用时还会把错误的数据写入模型,进一步加剧混乱。

修复方案:
首先,在cellForRowAt里把模型数据赋值给cell:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "RowCell") as! RowTableViewCell
    cell.selectionStyle = .none
    let sectionModel = itemsInTable[indexPath.section]
    
    if sectionModel.typeName == "textField" {
        switch indexPath.row {
        case 0:
            cell.TitleLbl.text = "Placeholder"
            cell.EntityLbl.text = "Hint"
            cell.txt.placeholder = "Placeholder"
            // 正确:把模型里的Hint值显示到textField
            cell.txt.text = sectionModel.content.Hint
            // 设置tag,方便后续识别是哪个section的哪个row
            cell.txt.tag = indexPath.section * 10 + indexPath.row
            cell.txt.delegate = self
        case 1:
            cell.TitleLbl.text = "پارامتر URL"
            cell.EntityLbl.text = "Query"
            cell.txt.placeholder = "پارامتر URL"
            cell.txt.text = sectionModel.content.Query
            cell.txt.tag = indexPath.section * 10 + indexPath.row
            cell.txt.delegate = self
        case 2:
            cell.TitleLbl.text = "متن"
            cell.EntityLbl.text = "Text"
            cell.txt.placeholder = "متن"
            cell.txt.text = sectionModel.content.Text
            cell.txt.tag = indexPath.section * 10 + indexPath.row
            cell.txt.delegate = self
        default:
            break
        }
    } else if sectionModel.typeName == "Button" {
        switch indexPath.row {
        case 0:
            cell.TitleLbl.text = "متن"
            cell.EntityLbl.text = "Label"
            cell.txt.placeholder = "متن روی دکمه"
            cell.txt.text = sectionModel.content.Label
            cell.txt.tag = indexPath.section * 10 + indexPath.row
            cell.txt.delegate = self
        case 1:
            cell.TitleLbl.text = "نوع عملیات"
            cell.EntityLbl.text = "Kind"
            cell.txt.placeholder = "اکسل، پای چارت"
            cell.txt.text = sectionModel.content.Kind
            cell.txt.tag = indexPath.section * 10 + indexPath.row
            cell.txt.delegate = self
        default:
            break
        }
    }
    return cell
}

然后实现UITextFieldDelegate方法,在用户修改textField内容时更新模型:

extension YourViewController: UITextFieldDelegate {
    func textFieldDidEndEditing(_ textField: UITextField) {
        // 通过tag解析section和row
        let section = textField.tag / 10
        let row = textField.tag % 10
        guard section < itemsInTable.count else { return }
        
        var model = itemsInTable[section]
        switch model.typeName {
        case "textField":
            switch row {
            case 0: model.content.Hint = textField.text
            case 1: model.content.Query = textField.text
            case 2: model.content.Text = textField.text
            default: break
            }
        case "Button":
            switch row {
            case 0: model.content.Label = textField.text
            case 1: model.content.Kind = textField.text
            default: break
            }
        default: break
        }
        // 把修改后的模型放回数组
        itemsInTable[section] = model
    }
}

最后总结

这三个错误里,header重用错误和cell赋值方向错误是导致section数据串位的主要原因,按照上面的方法修正后,你的表格应该就能正常工作了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:38:41