我有一个带有单元格的TableView
,并且一个单元格中有一个CollectionView
。
在CollectionView中,我的单元格带有UIImageViews。
如果我在CollectionView is visible
期间向数据源添加新元素,那么它将正常工作。
但是如果我在TableView中向下滚动,请添加新元素然后向上滚动,即使添加了新单元格,它们也会显示错误的图像。
视频:https://youtu.be/QwvMv2xaaAI
代码:
MainViewController (不是全部)
func addNewPhotos(newPhotosArray: [Photo]){
var collectionViewInserts : [IndexPath] = []
for (i in 0...newPhotosArray.count) {
// I add the new photos to the datasource
PhotosStore.shared.photos.insert(newPhotosArray[i], at: 0)
// Then save the indexPath what needs to be inserted
collectionViewInserts.insert(IndexPath(row: i, section: 0), at: 0)
}
if let cell = self.tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as? PhotosCell {
cell.photosCollectionView.performBatchUpdates({
cell.photosCollectionView.insertItems(at: collectionViewInserts)
}, completion: nil)
}
}
extension MainViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return PhotosStore.shared.photos.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCell", for: indexPath) as! PhotoCell
cell.photoImageView.downloadedFrom(link: (appSettings.url + "/resources/img/wp/prev/" + PhotosStore.shared.photos[indexPath.item].fileName))
return cell
}
}
PhotosCell:
import UIKit
class PhotosCell : UITableViewCell{
@IBOutlet weak var photosCollectionView : UICollectionView!
}
extension PhotosCell {
func setCollectionViewDataSourceDelegate<D: UICollectionViewDataSource & UICollectionViewDelegate>(_ dataSourceDelegate: D, forRow row: Int) {
// IF I PLACE A .reloadData() HERE, THEN IT WORKS BUT THEN THE CELL FLICKERS/JUMPS WHEN APPEARING ON SCREEN
let itemSize = 70
photosCollectionView.delegate = dataSourceDelegate
photosCollectionView.dataSource = dataSourceDelegate
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = UICollectionViewScrollDirection.horizontal
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.itemSize = CGSize(width: itemSize, height: itemSize)
photosCollectionView.setCollectionViewLayout(layout, animated: true)
photosCollectionView.tag = row
photosCollectionView.setContentOffset(photosCollectionView.contentOffset, animated:false) // Stops collection view if it was scrolling.
photosCollectionView.reloadData()
}
var collectionViewOffset: CGFloat {
set { photosCollectionView.contentOffset.x = newValue }
get { return photosCollectionView.contentOffset.x }
}
}
我怎么了?我确实正确更新了数据源,也确实对集合视图执行了批更新以插入正确的单元格。
更新的详细信息:
MainViewController:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Photos on top
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "PhotosCell", for: indexPath) as! PhotosCell
cell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
cell.collectionViewOffset = storedPhotosCollectionViewOffset[indexPath.row] ?? 0
return cell
}
... other cells ...
}
下载图像的扩展名:(我相信这不是问题,只是为了以防万一)
extension UIImageView {
func downloadedFrom(url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) {
image = nil
if let cachedImage = ImageCache.shared.loadCachedImage(url: url) {
image = cachedImage
return
}
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else {
DispatchQueue.main.async {
self.image = UIImage(named: "imageMissing")
}
return
}
DispatchQueue.main.async {
self.image = image
ImageCache.shared.cacheImage(image: image, url: url)
}
}.resume()
}
func downloadedFrom(link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
return downloadedFrom(url: url, contentMode: mode)
}
}
答案 0 :(得分:1)
cellForRowAt
中的第一名
cell.photosCollectionView.reloadData()
return cell
第二,您必须注意,每次滚动时都要下载图像(为imageView考虑一个虚拟图像或为其设置背景),因此请使用SDWebImage