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

UITableView嵌套UICollectionView选中状态切换代码实现咨询

解决UICollectionView单选选中状态问题(初始选中第一个+点击切换单选)

原代码存在两个核心问题:

  • CategoryCollectionViewCell的选中样式仅在awakeFromNib时初始化一次,后续状态变化不会自动更新UI
  • 未维护全局选中索引,点击新单元格时无法取消之前选中项的状态,也未实现初始选中第一个单元格的逻辑

以下是具体修改方案:

一、修改CategoryCollectionViewCell,实现状态变化自动更新UI

将样式更新逻辑抽为独立方法,通过重写isSelected属性监听状态变化,确保UI随选中状态实时更新:

class CategoryCollectionViewCell: UICollectionViewCell {

    override func awakeFromNib() {
        super.awakeFromNib()
        // 初始化时设置初始样式
        updateSelectedStyle()
    }
    
    // 重写isSelected属性,状态变化时同步更新按钮状态与UI
    override var isSelected: Bool {
        didSet {
            containerButton.isSelected = isSelected
            updateSelectedStyle()
        }
    }
    
    // 抽离选中样式更新逻辑
    private func updateSelectedStyle() {
        if containerButton.isSelected {
            titleLabel.textColor = .white
            containerButton.backgroundColor = .black
        } else {
            titleLabel.textColor = .black
            containerButton.backgroundColor = .white
        }
    }
}

二、修改CategoryTableViewCell,实现单选逻辑与初始选中

添加变量记录当前选中索引,初始化时选中第一个单元格,点击新单元格时取消之前选中项的状态:

class CategoryTableViewCell: UITableViewCell {
    let categoryList = ["All", "Question", "Community"]
    // 记录当前选中的索引,默认初始选中第0项
    private var selectedIndex: Int = 0
    
    override func awakeFromNib() {
        super.awakeFromNib()
        set(categoryList)
    }

    func set(_ dataList: [String]) {
        Observable.of(dataList).bind(to: collectionView.rx.items(cellIdentifier: "CategoryCollectionViewCell", cellType: CategoryCollectionViewCell.self)) { _, data, cell in
            cell.titleLabel.text = data
        }
        .disposed(by: disposeBag)
        
        // 异步执行初始选中,确保collectionView已完成布局
        DispatchQueue.main.async { [weak self] in
            guard let self = self, !dataList.isEmpty else { return }
            let initialIndexPath = IndexPath(item: 0, section: 0)
            self.collectionView.selectItem(at: initialIndexPath, animated: false, scrollPosition: .left)
        }
        
        collectionView.rx.itemSelected
            .subscribe(onNext: { [weak self] indexPath in
                guard let self = self else { return }
                // 取消之前选中的单元格状态
                if self.selectedIndex != indexPath.item {
                    let previousIndexPath = IndexPath(item: self.selectedIndex, section: 0)
                    if let previousCell = self.collectionView.cellForItem(at: previousIndexPath) as? CategoryCollectionViewCell {
                        previousCell.isSelected = false
                    }
                }
                // 更新当前选中状态与索引
                let currentCell = self.collectionView.cellForItem(at: indexPath) as? CategoryCollectionViewCell
                currentCell?.isSelected = true
                self.selectedIndex = indexPath.item
            })
            .disposed(by: disposeBag)
        
        collectionView.rx.setDelegate(self)
            .disposed(by: disposeBag)
    }
}

补充说明

  • 使用UICollectionView自带的selectItem(at:animated:scrollPosition:)处理初始选中,比直接修改单元格状态更符合组件规范
  • 重写单元格isSelected属性,确保UICollectionView的选中状态与自定义按钮状态保持同步,避免状态不一致
  • 通过selectedIndex变量维护全局选中状态,严格实现单选逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 07:55:41