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

使用[String: [String]]字典作为UITableView数据源的行数据匹配问题

解决UITableView中字典数据源的键值关联问题

你现在遇到的核心问题是数据结构和UITableView的数据源逻辑不匹配:你把所有descContent的元素合并到了requestedList里,而keyArr是每个header的集合,两者长度完全不同,用同一个indexPath.row去索引这两个数组,必然会出现键值错位的情况。

正确的做法是把UITableView改成分组结构,每个Section对应一个header(字典的key),每个Section里的Row对应该key对应的descContent数组元素。这样就能完美关联键和对应的值了,具体修改如下:

1. 精简数据变量

我们只需要保留有序的key数组和字典即可,requestedList可以直接删掉——因为我们不需要再把所有元素合并在一起:

var keyArr = [String]() // 维护Section的顺序,每个元素对应一个header
var requestedDictionary = [String: [String]]() // 存储header对应的descContent数组

2. 数据查询部分(小幅度优化)

原来的查询逻辑是对的,我们只需要去掉requestedList的填充,同时加上安全解包避免崩溃,最后记得刷新表视图:

let tQuery = PFQuery(className: "MyClass")
tQuery.whereKey("username", equalTo: PFUser.current()?.username as Any)
tQuery.selectKeys(["descContent", "header"])
do {
    let returnedObjects = try tQuery.findObjects()
    for object in returnedObjects {
        guard let header = object["header"] as? String else { continue }
        keyArr.append(header)
        if let descArr = object["descContent"] as? [String] {
            requestedDictionary[header] = descArr
        }
    }
    // 查询完成后刷新表视图
    tableView.reloadData()
} catch {
    print("查询出错: \(error.localizedDescription)")
}

3. 修改UITableView数据源方法

现在我们按Section来对应每个header,Row对应数组元素:

3.1 设置Section数量

每个Section对应一个header:

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

3.2 设置每个Section的Row数量

取当前Section对应的header,返回对应数组的长度:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let currentHeader = keyArr[section]
    return requestedDictionary[currentHeader]?.count ?? 0
}

3.3 配置Cell内容

现在可以正确获取当前Row对应的descContent元素,以及它所属的header:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "RequestViewCell", for: indexPath) as! RequestViewCell
    
    // 获取当前Section对应的header和数组
    let currentHeader = keyArr[indexPath.section]
    guard let descArr = requestedDictionary[currentHeader], indexPath.row < descArr.count else {
        return cell
    }
    let currentDesc = descArr[indexPath.row]
    
    // 配置Cell文本
    cell.descLbl.text = "Your ticket has been requested by \(currentDesc)"
    cell.refLbl.text = "for: \(currentHeader)"
    
    // 按钮Tag:用section+row组合,避免不同Section的Row Tag冲突
    cell.leftBtn.tag = indexPath.section * 1000 + indexPath.row
    cell.leftBtn.addTarget(self, action: #selector(leftClick(sender:)), for: .touchUpInside)
    cell.rightBtn.tag = indexPath.section * 1000 + indexPath.row
    cell.rightBtn.addTarget(self, action: #selector(rightClick(sender:)), for: .touchUpInside)
    
    return cell
}

3.4 可选优化:添加Section Header

如果想在每个Section顶部显示对应的header,可以实现这个方法:

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return keyArr[section]
}

为什么原来的方法会出错?

举个例子:假设你从Parse拿到2个对象,第一个对象的header是"Header A",对应descContent有3个元素;第二个对象的header是"Header B",对应descContent有2个元素。那么:

  • keyArr的长度是2,元素是["Header A", "Header B"]
  • requestedList的长度是5,元素是[A1, A2, A3, B1, B2]
    当indexPath.row=1时,requestedList[1]是A2,但keyArr[1]是Header B,这就导致了错误的关联,而分组的方式就能彻底避免这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 11:32:27