tvOS中UICollectionView动态设置Item数量时单元格不渲染问题
问题:tvOS中UITableView嵌套UICollectionView,动态设置Item数量时单元格不渲染
我正在开发一款tvOS应用,结构是UITableView每行嵌套一个UICollectionView,已经禁用了UITableView的焦点,让UICollectionView单元格可以获取焦点。现在遇到的问题是:当在numberOfItemsInSection里返回静态数值(比如10)时,UICollectionView的单元格能正常渲染;但改成动态取categoryDetails?.media?.count时,单元格完全不显示。
相关代码如下:
class CategoryCVContainerCell: UITableViewCell { @IBOutlet weak var categoryCollectionView: UICollectionView! var cellType:CellType? var sourceViewController: UIViewController? var media : Media? // 注:代码中用到了categoryDetails,但未看到该属性的定义,推测应为var categoryDetails: CategoryDetails? override func awakeFromNib() { super.awakeFromNib() categoryCollectionView.register(UINib(nibName: "VODType1CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "VODType1CollectionViewCell") } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) } func configureCellUI() { categoryCollectionView.reloadSections(IndexSet(integer: 0)) } } extension CategoryCVContainerCell : UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { print("////////************------------////////// \(categoryDetails?.media?.count ?? 0)") let itemsCount = categoryDetails?.media?.count ?? 0 // 动态取值时不渲染单元格 // let itemsCount = 10 // 静态值时可正常渲染 return itemsCount } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "VODType1CollectionViewCell", for: indexPath) return cell } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: 400.0, height: 250.0) } }
排查与解决方案
1. 确认数据源赋值时机与正确性
- 先补全
categoryDetails属性的定义,确保类型匹配; - 检查
categoryDetails及media数组的赋值是否在调用configureCellUI()之前完成。如果先刷新UICollectionView再赋值数据源,此时拿到的是空值,自然不会渲染单元格; - 查看打印日志的数值,如果输出0,说明数据源本身为空,需要确认接口返回或本地数据加载是否正常。
2. 手动绑定UICollectionView的数据源与代理
tvOS环境下,通过IB绑定的代理偶尔会出现失效情况,建议在awakeFromNib()里手动设置:
override func awakeFromNib() { super.awakeFromNib() categoryCollectionView.register(UINib(nibName: "VODType1CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "VODType1CollectionViewCell") categoryCollectionView.dataSource = self categoryCollectionView.delegate = self }
3. 替换刷新方法确保生效
把configureCellUI()中的局部刷新换成全量刷新,避免嵌套视图下的局部刷新异常:
func configureCellUI() { categoryCollectionView.reloadData() }
4. 处理UITableView的复用逻辑
由于UITableViewCell存在复用机制,给嵌套cell赋值时先清空旧数据,避免残留的空数据源影响:
// 在UITableView的cellForRowAt方法中 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryCVContainerCell", for: indexPath) as! CategoryCVContainerCell // 先清空旧数据源 cell.categoryDetails = nil // 再赋值新数据 cell.categoryDetails = yourDataList[indexPath.row] // 刷新UICollectionView cell.configureCellUI() return cell }
5. 强制刷新布局
如果数据更新后布局未自动更新,可在刷新后强制触发布局:
func configureCellUI() { categoryCollectionView.reloadData() categoryCollectionView.layoutIfNeeded() }
内容的提问来源于stack exchange,提问作者AVY
相关产品推荐
相关产品推荐

