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

如何保存segmentedController内共用tableView的选中行状态

解决方案

你现有代码已经单独存储了两个分段的选中行位置,只需补充分段切换时的状态同步逻辑即可实现状态保留,具体修改如下:


基础实现(每个分段单选,切换保留选中状态)

步骤1:完善cellForRow的选中状态配置

在cellForRowAt方法中,根据当前选中的分段,判断当前行是否为对应分段的选中行,主动设置cell的选中样式:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "CommonCell", for: indexPath)
    if segmentedControl.selectedSegmentIndex == 0 {
        cell.textLabel?.text = viewModel.genres[indexPath.row]
        // 匹配分类分段的选中状态
        cell.accessoryType = viewModel.selectedGenr == indexPath.row ? .checkmark : .none
    } else {
        cell.textLabel?.text = viewModel.years[indexPath.row]
        // 匹配年份分段的选中状态
        cell.accessoryType = viewModel.selectedYear == indexPath.row ? .checkmark : .none
    }
    return cell
}

步骤2:添加分段切换监听

切换分段时重新加载tableView,触发上面的cell配置逻辑,同步对应分段的选中状态:

// 视图加载时给分段控件添加切换监听
segmentedControl.addTarget(self, action: #selector(segmentDidChange(_:)), for: .valueChanged)

// 切换触发方法
@objc func segmentDidChange(_ sender: UISegmentedControl) {
    tableView.reloadData()
}

你原有的didSelectRowAt逻辑无需修改,已经满足单选场景下的选中值存储需求。


性能优化方案(避免全量刷新)

如果不想触发全列表刷新,可以在切换分段时手动更新选中行状态,性能更优:

@objc func segmentDidChange(_ sender: UISegmentedControl) {
    if sender.selectedSegmentIndex == 0 {
        // 切换到分类分段:清除年份分段的选中高亮,设置分类分段的选中高亮
        if let preSelectedYear = viewModel.selectedYear {
            tableView.deselectRow(at: IndexPath(row: preSelectedYear, section: 0), animated: false)
        }
        if let currentSelectedGenr = viewModel.selectedGenr {
            tableView.selectRow(at: IndexPath(row: currentSelectedGenr, section: 0), animated: false, scrollPosition: .none)
        }
    } else {
        // 切换到年份分段:清除分类分段的选中高亮,设置年份分段的选中高亮
        if let preSelectedGenr = viewModel.selectedGenr {
            tableView.deselectRow(at: IndexPath(row: preSelectedGenr, section: 0), animated: false)
        }
        if let currentSelectedYear = viewModel.selectedYear {
            tableView.selectRow(at: IndexPath(row: currentSelectedYear, section: 0), animated: false, scrollPosition: .none)
        }
    }
}

扩展实现(每个分段支持多选,保留所有选中行)

如果需要每个分段可选中多行,只需修改ViewModel的存储结构即可:

  1. 把原有的单个可选Int改为Set存储选中行索引
// ViewModel修改
var selectedGenres: Set<Int> = []
var selectedYears: Set<Int> = []
  1. 修改didSelectRowAt逻辑
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if segmentedControl.selectedSegmentIndex == 0 {
        if viewModel.selectedGenres.contains(indexPath.row) {
            viewModel.selectedGenres.remove(indexPath.row)
        } else {
            viewModel.selectedGenres.insert(indexPath.row)
        }
    } else {
        if viewModel.selectedYears.contains(indexPath.row) {
            viewModel.selectedYears.remove(indexPath.row)
        } else {
            viewModel.selectedYears.insert(indexPath.row)
        }
    }
    tableView.reloadRows(at: [indexPath], with: .automatic)
}
  1. 修改cellForRowAt的状态判断逻辑
// 分类分段判断
cell.accessoryType = viewModel.selectedGenres.contains(indexPath.row) ? .checkmark : .none
// 年份分段判断
cell.accessoryType = viewModel.selectedYears.contains(indexPath.row) ? .checkmark : .none

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 03:09:03