UICollectionView 重复单元格
Posted
技术标签:
【中文标题】UICollectionView 重复单元格【英文标题】:UICollectionView repeating cell 【发布时间】:2016-02-01 23:15:17 【问题描述】:我有一个 UICollectionView,每个单元格中都有一个图像。这些图像由 URL 加载。但是,当一个单元格滚动出视图时,它会在再次加载之前显示另一个单元格的图像一秒钟。我不知道为什么会这样。
这是我的代码:
我的 UIImageView 扩展从 url 加载:
extension UIImageView
public func imageFromUrl(urlString: String)
Alamofire.request(.GET, urlString).responseJSON
response in
if let tilbudimage = UIImage(data: response.data!)
self.image = tilbudimage
UICollectionView:
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
return 1
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
print(DealArr.count)
return DealArr.count
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("DealCell", forIndexPath: indexPath) as! DealCell
let deal = self.DealArr[indexPath.row]
cell.backgroundColor = UIColor.whiteColor()
cell.DealImage.imageFromUrl(deal["image"].string!)
cell.DealLabel.text = deal["title"].string! + ", " + String(deal["price"].int!) + "kr."
cell.DealDescription.text = deal["description"].string!
cellarr.append(cell)
return cell
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
return CGSizeMake(collectionView.frame.width, 450)
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets
return UIEdgeInsetsMake(0, 0, 0, 0)
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat
return 0.0
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat
return 1.0
【问题讨论】:
【参考方案1】:显示单元格时,您没有清除图像。单元格在从屏幕上移除后会被重复使用,因此在显示之前,您需要确保清除任何不应被转移的数据。通常这是通过将任何数据设置为新值来处理的。对于您的图像,它不会立即设置新图像,而是调度一个异步任务来获取图像,然后在单元格中显示该图像。所以图像将被重新分配,但它会等到它收到来自服务器的带有新图像的响应,然后再清除旧图像。
要解决此问题,您应该在加载新图像之前将图像设置为 nil。
cell.DealImage.image = nil
cell.DealImage.imageFromUrl(deal["image"].string!)
或者您的扩展程序也可以在加载新图像之前先清除图像。
extension UIImageView
public func imageFromUrl(urlString: String)
image = nil
Alamofire...
您还可以通过在重用单元格时取消任何待处理的请求来提高加载效率。如果您有兴趣,可以在 raywenderlich 上找到一个很好的教程:http://www.raywenderlich.com/85080/beginning-alamofire-tutorial
您还可以通过在下载图像后缓存图像来提高性能。为此,您可以使用 NSCache 的实例。
let imageCache = NSCache()
extension UIImageView
public func imageFromUrl(urlString: String)
if let image = imageCache.objectForKey(urlString) as? UIImage
self.image = image
else
Alamofire.request(.GET, urlString).responseJSON
response in
if let tilbudimage = UIImage(data: response.data!)
self.image = tilbudimage
imageCache.setObject(tilbudimage, forKey: urlString)
【讨论】:
感谢您的回复@esthepiking。但是通过在加载图像之前将图像设置为 nil,我会在图像出现之前看到一个白色背景(难怪我将图像设置为 nil 时),我不会像 instagram 那样加载更顺畅。 哦,你也可以将它设置为一些默认值,或者加载图像。它不一定非得是 nil,你只需要将它设置为某个值,这样它就不会显示之前加载的图像 好吧。但是有没有办法阻止它在第一次加载时再次加载图像。我发现每次一个单元格不在视野中时都需要在图像可见时再次请求图像,这很烦人。在 instagram 中,它的行为并非如此。服务器速度是否会在其中发挥作用? 哦,您可以通过在下载后缓存图像来改进。我在答案中添加了一个缓存示例【参考方案2】:您可以从自定义 UICollectionViewCell 类中使用这个。
override func prepareForReuse()
self.imageView.image = nil // or placeholder image
super.prepareForReuse()
【讨论】:
以上是关于UICollectionView 重复单元格的主要内容,如果未能解决你的问题,请参考以下文章
UICollectionView 水平分页仅在第一页上每行显示 3 个单元格
在 UICollectionView/UITableView 中为滚动视图的偏移设置动画会导致单元格过早消失