概览
我在我的 collectionView 单元格中使用 SDWebImage 从 Web 服务器下载图像。
if floor.hasTitleImage != nil {
self.floorImageView.sd_setImageWithURL(NSURL(string:(floor.hasTitleImage?.imageURL)!), placeholderImage: UIImage(named: "Placeholder"), completed: { (imageDownloaded, error, cacheType, url) in
if imageDownloaded.size.width > 300 {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
let resizedImage = imageDownloaded.resizePreservingAspectRatio(toSize: CGSize(width: 300, height: 300))
SDImageCache.sharedImageCache().removeImageForKey(NSURL(string:(floor.hasTitleImage?.imageURL)!)?.absoluteString, fromDisk: true, withCompletion: {
SDImageCache.sharedImageCache().storeImage(resizedImage, forKey: NSURL(string:(floor.hasTitleImage?.imageURL)!)?.absoluteString, toDisk: true)
})
})
}
})
}
else{
self.floorImageView.image = UIImage(named: "Placeholder")
}
现在这段代码正在做的是使用存储在名为 floor 的核心数据元素中的 url 下载图像。现在下载的图像比我的 ImageView 大得多,所以我将它的大小调整到 300 像素左右。
我知道 SDWebImage 默认情况下会进行密集缓存,并使用 url 的绝对字符串作为其缓存的键。所以一旦调整大小!我用调整大小后的图片替换原始图片。
问题
一切如预期般顺利!直到我用低网速测试它导致图像下载延迟。
如果图像下载需要时间,直到那时如果我滚动 tableView 并且单元格被重用,一旦图像下载 SDWebImage 加载单元格的 imageView 但最终导致错误的单元格和错误的图像。
虽然这种情况只发生一次,但下一次图像将从缓存中加载,一切正常。但这是预期的行为还是我做错了什么???
我能想到的解决方案:
由于 sd_setImageWithURL 默认情况下使用下载的图像设置 imageView 的值,而不是使用 sd_setImageWithURL 下载图像,如果我可以使用,
if floor.hasTitleImage != nil { if let downloadedImage = SDImageCache.sharedImageCache().imageFromMemoryCacheForKey(NSURL(string:(floor.hasTitleImage?.imageURL)!)?.absoluteString){ self.floorImageView.image = downloadedImage } else if let diskImage = SDImageCache.sharedImageCache().imageFromDiskCacheForKey(NSURL(string:(floor.hasTitleImage?.imageURL)!)?.absoluteString){ self.floorImageView.image = diskImage } else{ let downloadManager = SDWebImageManager.sharedManager(); downloadManager.downloadImageWithURL(NSURL(string:(floor.hasTitleImage?.imageURL)!), options: [], progress: nil, completed: { (downloadedImage, error, cacheType, finished, url) in if downloadedImage.size.width > 300 { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { let resizedImage = downloadedImage.resizePreservingAspectRatio(toSize: CGSize(width: 300, height: 300)) SDImageCache.sharedImageCache().removeImageForKey(NSURL(string:(floor.hasTitleImage?.imageURL)!)?.absoluteString, fromDisk: true, withCompletion: { SDImageCache.sharedImageCache().storeImage(resizedImage, forKey: NSURL(string:(floor.hasTitleImage?.imageURL)!)?.absoluteString, toDisk: true) }) if floor.hasTitleImage?.imageURL != nil && floor.hasTitleImage?.imageURL! == url{ dispatch_async(dispatch_get_main_queue(), { self.floorImageView.image = SDImageCache.sharedImageCache().imageFromMemoryCacheForKey(NSURL(string:(floor.hasTitleImage?.imageURL)!)?.absoluteString) self.reloadInputViews() }) } }) } }) } } else{ self.floorImageView.image = UIImage(named: "Placeholder") }
虽然它有效,但它只会在我滚动 tableView 时加载图像 :(
问题:
sd_setImageWithURL 所做的是预期的行为吗??我的意思是每一个使用带有 tableView 或 CollectionView 的 SDWebImage 的应用程序都必须面对这个正确的?因此,如果没有人面对它,我一定做错了什么:(我做错了什么吗?
使用 SDWebImageManager.sharedManager 所做的事情是否正确???需要那么长的代码吗?检查内存缓存,然后检查磁盘缓存,最后调用下载图像是不是太多了:o
为什么我的第二种方法在下载后不加载图像并期望 Collection View 滚动并重新加载单元格以显示图像?
编辑
我解决了第三个问题:)对不起我的错误。我正在比较 if floor.hasTitleImage?.imageURL != nil && floor.hasTitleImage?.imageURL! == url{
这是错误的,因为上面的 url 是 NSURL
而 floor.hasTitleImage?.imageURL!是 NSString
。
所以更新的解决方案:
if floor.hasTitleImage?.imageURL != nil && floor.hasTitleImage!.imageURL! == url.absoluteString{
dispatch_async(dispatch_get_main_queue(), {
self.floorImageView.image = SDImageCache.sharedImageCache().imageFromDiskCacheForKey(NSURL(string:(floor.hasTitleImage?.imageURL)!)?.absoluteString)
self.setNeedsLayout()
})
}
虽然我的第二种方法现在下载图像并正确更新单元格,但与 sd_setImageWithURL 相比,现在图像下载速度非常慢。
有什么方法可以使用 method1 sd_setImageWithURL 并正确更新图像?
请帮帮我!!做错了什么!提前致谢:)
最佳答案
- Is what sd_setImageWithURL doing is expected behaviour ?? I mean every single one of the app using SDWebImage with tableView or CollectionView must have faced this correct ?? So if no body faced it I must be doing something wrong :( Am I doing anything wrong ?
不,这不是预期的行为。我正在使用 SDWEbImage 以及 tableView 和 collectionView,两者都工作正常。
- Is what am doing using SDWebImageManager.sharedManager is correct ??? Is that long code required? Checking memory cache then disk cache and finally making call to download image isn't it too much :o
您不必自己缓存图像,SDWebImage 会为您处理缓存过程(在内存和磁盘中)。
如果您需要在缓存和显示之前调整图像大小,我认为最好通过工具来实现 SDWebImageManagerDelegate这允许您在图像下载之后但在缓存和显示之前转换图像。
更新:
如果您使用 sd_setImageWithURL
,还有另一种防止错误分配图像的解决方案是通过覆盖 UICollectionViewCell 子类中的 prepareForReuse()
方法并调用 sd_cancelCurrentImageLoad()
在 imageView 上并将图像设置为 nil
。
希望这对您有所帮助。
关于ios - SDWebImage 的 sd_setImageWithURL 在滚动时用图像更新了错误的单元格!!这是预期的行为吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39164701/