UITableViewCell嵌套UICollectionView分页加载图片重复问题求助
问题描述
我实现了一个UITableView,每个UITableViewCell中嵌套了一个UICollectionView用于横向轮播图片。每个UITableViewCell通过ViewModel配置,ViewModel包含嵌套UICollectionView所需的imageURL数组数据源。首次加载一切正常,但加载第二页数据后,第二页的UITableViewCell图片与第一页重复,不过CollectionView下方的PageControl页数与imageURL数组数量匹配,显示正确。
测试场景:首次加载5条UITableView数据,前2条的嵌套UICollectionView各有1张图片;加载第二页的2条数据后,这2条的图片与第一页前2条重复,但PageControl页数正确。
注:不建议使用prepareForReuse()重置内容,除非别无选择。
相关代码
UITableView的cellForRow方法
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: DataTableViewCell.id, for: indexPath) as! DataTableViewCell cell.delegate = self cell.configureWith(viewModel.getViewModelAt(indexPath.row)) return cell }
嵌套UICollectionView的cellForItem方法
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { if indexPath.row == 0 { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CensoredDataCollectionViewCell.id, for: indexPath) as! CensoredDataCollectionViewCell cell.setRemoteImage(with: viewModel.photoGalleryURLStrings[0]) return cell } let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ImageCollectionViewCell.id, for: indexPath) as! ImageCollectionViewCell let imageURLString = viewModel.photoGalleryURLStrings[indexPath.row - 1] cell.setRemoteImage(with: imageURLString) return cell }
setRemoteImage方法用于从服务器加载图片到cell的ImageView,indexPath.row - 1是因为UICollectionView首项为特殊单元格。
滚动加载下一页的代码
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { if indexPath.row == viewModel.dataCount - 1 { tableViewFooterLoadingWheel.startAnimating() viewModel.downloadData { [weak self] moreData in if moreData { DispatchQueue.main.async { self?.tableView.reloadData() } } DispatchQueue.main.async { self?.tableViewFooterLoadingWheel.stopAnimating() } } } }
网络请求成功追加数据的代码
case .success(let result): strongSelf.data.append(contentsOf: result.results) if let next = result.next { strongSelf.dataURL = next } else { strongSelf.dataURL = nil } completion(true)
UITableViewCell的configureWith方法
func configureWith(_ viewModel: dataViewModel) { self.dataViewModel = viewModel loadingWheel.startAnimating() avatarImageView.loadImageFromURL(dataViewModel.avatarImageURLString) { [weak self] in DispatchQueue.main.async { self?.loadingWheel.stopAnimating() } } statusLabel.text = dataViewModel.status createdAtLabel.text = dataViewModel.created photoGalleryPageControl.numberOfPages = dataViewModel.photoGalleryURLStrings.count likesCountLabel.text = "\(dataViewModel.likeCount)" likesButton.isSelected = dataViewModel.isLiked commentsCountLabel.text = dataViewModel.commentCount }
问题原因与解决方案
核心问题
UITableViewCell复用后,嵌套的UICollectionView没有重新加载数据。configureWith方法仅更新了PageControl的页数,但未触发UICollectionView的数据源刷新,导致复用的CollectionView仍显示之前cell的图片数据。
解决步骤
在configureWith方法末尾添加UICollectionView的刷新代码:
func configureWith(_ viewModel: dataViewModel) { self.dataViewModel = viewModel // 原有代码保持不变... commentsCountLabel.text = dataViewModel.commentCount // 刷新嵌套的CollectionView,加载当前ViewModel对应的图片数据 photoGalleryCollectionView.reloadData() }
补充说明
- 调用
reloadData()会让CollectionView重新执行cellForItemAt方法,基于当前cell绑定的ViewModel获取正确的图片URL,彻底避免复用旧数据的问题。 - 无需使用
prepareForReuse(),因为配置cell时主动刷新了CollectionView,确保每次复用都加载最新的数据源。
内容的提问来源于stack exchange,提问作者Vcubbz
相关产品推荐
相关产品推荐

