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

在UITableView中嵌入UICollectionView遇越界及滚动内容异常求助

问题原因分析

  1. 数组下标越界

    • CustomCell中的viewModel未做可选类型处理,初始化阶段若collectionView先于viewModel赋值调用数据源方法,会因访问空数组下标触发越界错误。
    • 赋值viewModel后未立即刷新collectionView,UITableView复用cell时,旧数据未被替换,导致数据源与展示内容不匹配,进而触发下标越界。
  2. 滚动时单元格内容异常

    • UITableView的复用机制导致CustomCell被重复利用,但UICollectionView未在每次赋值viewModel后刷新,旧数据残留引发内容错乱。
    • sizeForItemAt中使用baseCollectionView.bounds.width计算item尺寸,cell未完成布局时该宽度可能为0或错误值,导致collectionView布局异常,滚动时内容显示混乱。

解决方案

1. 修复数组下标越界

  • 修改CustomCell的viewModel定义,添加可选类型并在赋值后刷新collectionView:
    class CustomCell: UITableViewCell {
        var viewModel: [Features]? {
            didSet {
                baseCollectionView.reloadData()
            }
        }
        // 其他原有代码...
    }
    
  • 安全访问collectionView数据源,处理viewModel为nil的情况:
    extension CustomCell : UICollectionViewDelegate , UICollectionViewDataSource , UICollectionViewDelegateFlowLayout {
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return viewModel?.count ?? 0
        }
    
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CollectionViewCell.identifier, for: indexPath) as? CollectionViewCell,
                  let item = viewModel?[indexPath.row] else {
                return UICollectionViewCell()
            }
            cell.titleView.text = item.title
            cell.overView.text = item.overview
            return cell
        }
        // 其他原有代码...
    }
    

2. 修复滚动内容异常

  • 清空复用cell的旧数据,在prepareForReuse中重置viewModel并刷新collectionView:
    class CustomCell: UITableViewCell {
        // 其他原有代码...
        override func prepareForReuse() {
            super.prepareForReuse()
            viewModel = nil
            baseCollectionView.reloadData()
        }
    }
    
  • 修正collectionView item尺寸计算逻辑,使用cell的宽度替代未布局完成的collectionView bounds:
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let width = self.bounds.width / 2
        let height = collectionView.bounds.height
        return CGSize(width: width, height: height)
    }
    
    或者在cell布局完成后更新collectionView布局:
    override func layoutSubviews() {
        super.layoutSubviews()
        if let layout = baseCollectionView.collectionViewLayout as? UICollectionViewFlowLayout {
            layout.itemSize = CGSize(width: self.bounds.width / 2, height: baseCollectionView.bounds.height)
            baseCollectionView.collectionViewLayout.invalidateLayout()
        }
    }
    

3. 额外优化:增强UITableView数据源安全性

在ViewController的titleForHeaderInSection中添加越界判断:

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    guard section < featuresVM.count else { return nil }
    return featuresVM[section].imageName
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 10:25:34