Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios SDWebImage';s sd_setImageWithURL在滚动时使用图像更新错误的单元格!!这是预期的行为吗?_Ios_Swift_Image_Sdwebimage - Fatal编程技术网

Ios SDWebImage';s sd_setImageWithURL在滚动时使用图像更新错误的单元格!!这是预期的行为吗?

Ios SDWebImage';s sd_setImageWithURL在滚动时使用图像更新错误的单元格!!这是预期的行为吗?,ios,swift,image,sdwebimage,Ios,Swift,Image,Sdwebimage,概述 我正在collectionView单元格中使用SDWebImage从web服务器下载图像 if floor.hasTitleImage != nil { self.floorImageView.sd_setImageWithURL(NSURL(string:(floor.hasTitleImage?.imageURL)!), placeholderImage: UIImage(named: "Placeholder"), completed: { (imageDow

概述

我正在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大很多,所以我将它的大小调整到300px左右

我知道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所做的是预期行为吗?我的意思是,使用SDWebImage with tableView或CollectionView的每个应用程序都必须正确面对这一点??因此,如果没有人面对它,我一定是做错了什么:(我做错了什么吗

  • 我使用SDWebImageManager.sharedManager所做的是正确的吗???需要很长的代码吗?先检查内存缓存,然后检查磁盘缓存,最后调用下载映像,这不是太多了吗

  • 为什么我的第二种方法在下载图像后不加载图像,并期望集合视图滚动并重新加载单元格以显示图像

  • 编辑

    我解决了第三个问题:)对不起,我错了。我在比较
    if floor.hasttleimage?.imageURL!=nil&&floor.hasttleimage?.imageURL!==url{
    这是错误的,因为上面的url是
    NSURL
    其中as floor.hasttleimage?.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正确更新图像

    请帮帮我!!我做错了什么!!提前谢谢:)

  • sd_setImageWithURL所做的是预期行为吗?我的意思是,使用SDWebImage with tableView或CollectionView的每个应用程序都必须正确面对这一点??因此,如果没有人面对它,我一定是做错了什么:(我做错了什么吗

  • 不,这不是预期的行为。我使用SDWEbImage以及tableView和collectionView,两者都可以正常工作

  • 我使用SDWebImageManager.sharedManager所做的是正确的吗???需要很长的代码吗?先检查内存缓存,然后检查磁盘缓存,最后调用下载映像,这不是太多了吗
  • 您不必自己缓存映像,SDWebImage会为您处理缓存过程(在内存和磁盘中)

    如果您需要在缓存和显示之前调整图像大小,我认为最好通过实现来实现,该实现允许您在下载图像后但在缓存和显示之前对图像进行变换

    更新:

    如果您使用
    sd\u setImageWithURL
    ,另一种防止错误分配图像的解决方案是重写UICollectionViewCell子类中的
    prepareForReuse()
    方法,并在imageView上调用
    sd\u cancelCurrentImageLoad()
    ,然后将图像设置为
    nil


    希望有帮助。

    “不,这不是预期的行为。我使用的是SDWEbImage,tableView和collectionView都可以正常工作。”你是否尝试过在你的单元格启动图像请求时滚动单元格,并在图像下载时重新使用它。我使用sd_setImageWithURL时是否有任何错误?为什么它对我不起作用???我已经为你创建了演示项目,请看一看-我会看一看:)明天之前让你知道:)我感谢你的努力,因此投票结果是:)尝试了你的代码伙伴,工作很好,我过去也使用过SDWebImage,但从未遇到过任何问题:(这是我第一次遇到错误的图像更新问题:(您和我的代码中唯一的区别是我在集合视图中使用自定义布局。这是否会影响SDWebImage中的内容:(因为当我使用SDWebImage的方式与您在我的代码中使用的方式完全相同时,它再次失败:(