如何将两组数据集合并展示在同一UITableView中并实现行级所属数据源识别
双独立数据源合并到单UITableView的实现方案
针对两组独立字符串数组合并展示的需求,核心是建立indexPath和对应数据源数组的映射关系,根据是否需要分区展示,有两种可落地的实现路径:
方案一:按Section隔离两组数据源(长期维护首选)
这种实现方式用UITableView原生的section属性作为数据源来源的天然标识,不需要手动计算行偏移量,逻辑清晰、出错概率极低,尤其适配动态增删数据、手势操作的场景。
各代理方法的配套逻辑如下:
numberOfSections(in:):返回固定2个section,分别对应你的两组数据源tableView(_:numberOfRowsInSection:):根据当前section值,分别返回对应数据源数组的长度tableView(_:cellForRowAt:):通过indexPath.section判断当前行的数据源来源,从对应数组取文本赋值给celltableView(_:trailingSwipeActionsConfigurationForRowAt:):同样通过section值判定来源,配置不同的滑动操作逻辑
对应可直接运行的代码示例:
// 原有数据源定义 var myFirstData = ["Hello", "Hi"] var mySecondData = ["Goodbye", "Bye"] // UITableView代理实现 func numberOfSections(in tableView: UITableView) -> Int { return 2 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch section { case 0: return myFirstData.count case 1: return mySecondData.count default: return 0 } } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "BaseTableViewCell", for: indexPath) let content: String switch indexPath.section { case 0: content = myFirstData[indexPath.row] case 1: content = mySecondData[indexPath.row] default: content = "" } cell.textLabel?.text = content return cell } func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { let deleteAction = UIContextualAction(style: .destructive, title: "删除") { [weak self] _, _, completion in guard let self = self else { return } switch indexPath.section { case 0: self.myFirstData.remove(at: indexPath.row) case 1: self.mySecondData.remove(at: indexPath.row) default: break } tableView.deleteRows(at: [indexPath], with: .automatic) completion(true) } return UISwipeActionsConfiguration(actions: [deleteAction]) }
方案二:单Section平铺合并(适配无分区展示需求)
如果需求要求两组数据连续展示、不做分区隔离,就需要通过固定的行边界计算,判断当前行的数据源归属:
- 整表仅保留1个section,总行数为两个数组长度之和
- 判断规则:若当前
indexPath.row小于第一组数组的长度,该行属于第一组数据源,行索引可直接使用;若大于等于该阈值,就属于第二组数据源,需要用当前行号 - 第一组数组长度换算成第二组数组内的真实行索引
对应代码示例:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return myFirstData.count + mySecondData.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "BaseTableViewCell", for: indexPath) let firstDataRange = 0..<myFirstData.count let content: String if firstDataRange.contains(indexPath.row) { content = myFirstData[indexPath.row] } else { let secondGroupRealRow = indexPath.row - myFirstData.count content = mySecondData[secondGroupRealRow] } cell.textLabel?.text = content return cell } func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { let deleteAction = UIContextualAction(style: .destructive, title: "删除") { [weak self] _, _, completion in guard let self = self else { return } let firstDataRange = 0..<self.myFirstData.count if firstDataRange.contains(indexPath.row) { self.myFirstData.remove(at: indexPath.row) } else { let secondGroupRealRow = indexPath.row - self.myFirstData.count self.mySecondData.remove(at: secondGroupRealRow) } tableView.deleteRows(at: [indexPath], with: .automatic) completion(true) } return UISwipeActionsConfiguration(actions: [deleteAction]) }
注意事项:如果采用单Section平铺模式,每次修改数据源后需要主动刷新UITableView的行数,避免动态增删数据时行偏移量计算错位、引发索引越界崩溃。分Section的实现方式因为不需要维护全局偏移量,长期维护成本更低,是多数据源合并的官方推荐实现方式。
内容的提问来源于stack exchange,提问作者Ashwin Paudel
相关产品推荐
相关产品推荐

