所以我创建了一个iOS应用程序,可以让你浏览Unsplash壁纸,我使用UICollectionView在单元格中加载图像,但每当我滚动图像时,我都会将图像更改返回到另一个图像。
这是代码
(col1, col2, col3)
答案 0 :(得分:2)
@toddg解决方案是正确的。但是仍然存在重用细胞的问题。
如果在网络呼叫完成之前重新使用该小区,则它会将下载的图像分配给另一个小区。
所以我改变了代码如下。
var imageArray: [UIImage]?
let downloadQueue = dispatch_queue_create("com.donbytyqi.Papers", nil)
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! ImageCollectionViewCell
if let oldImage: UIImage = imageArray[indexPath.row] {
cell.imageView.image = oldImage
return cell
} else {
cell.imageView.image = nil;
downloadImage(indexPath);
}
return cell
}
func downloadImage(indexPath: NSIndexPath) {
dispatch_async(downloadQueue) {
let imageURL = NSURL(string: "https://unsplash.it/200/300/?random")
let imageData = NSData(contentsOfURL: imageURL!)
var image: UIImage?
if imageData != nil {
image = UIImage(data: imageData!)
}
let cell = self.collectionView .cellForItemAtIndexPath(indexPath) as! ImageCollectionViewCell
dispatch_async(dispatch_get_main_queue()) {
cell.imageView.image = image
}
}
}
希望这有帮助。
答案 1 :(得分:1)
collectionView.dequeueReusableCellWithReuseIdentifier
重复使用已创建的单元格(如果有可用的单元格)。所以你要将你以前的一个单元格出列。
加载图片的网址每次调用时都会生成一个随机图片。
因此,当您滚动到集合视图的第一行不在屏幕上的点时,这些单元格将被重用。然后,当您向上滚动时,将使用"https://unsplash.it/200/300/?random"
绕过这种方法的一种方法是根据单元格索引保留所有图像的数组。当然,如果你的图像非常大和/或你有一个非常大的集合视图,你可能会耗尽内存。
看一下我嘲笑过的代码。我还没有确认代码确实有效。
//instance var to store your images
var imageArray: [UIImage]?
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! ImageCollectionViewCell
// Check if we have already loaded an image for this cell index
if let oldImage: UIImage = imageArray[indexPath.row] {
cell.imageView.image = oldImage
return cell
} else {
// remove the old image, before downloading the new one
cell.imageView.image = nil
}
let downloadQueue = dispatch_queue_create("com.donbytyqi.Papers", nil)
dispatch_async(downloadQueue) {
let imageURL = NSURL(string: "https://unsplash.it/200/300/?random")
let imageData = NSData(contentsOfURL: imageURL!)
var image: UIImage?
if imageData != nil {
image = UIImage(data: imageData!)
// Save image in array so we can access later
imageArray.insert(image, atIndex: indexPath.row)
}
dispatch_async(dispatch_get_main_queue()) {
cell.imageView.image = image
}
}
return cell
}
答案 2 :(得分:0)
让我解释一下实际发生了什么
当您滚动并返回时,您实际上会看到之前显示的单元格,其中包含先前下载的图像(因为dequeueReusableCellWithReuseIdentifier:
),您将继续看到该图像,直到您的新图像无法下载,即执行{{1}行。
所以,你必须做以下事情:
在cell.imageView.image = image
行之后设置cell.imageView.image = nil
,如下所示:
dequeueReusableCellWithReuseIdentifier:
这将从imageView删除以前下载的图像,直到新图像下载。
您应该使用SDWebImage或UIImageView+AFNetworking之类的内容来进行具有缓存支持的异步图像下载,因为每次调用您的方法时,都会一次又一次地下载图像而不是缓存图片,这就是浪费交通。