SDWebImage Library - placeholder from URL

904 views Asked by At

I'm using SDWebImage to download and cache images in an UITableView asynchronously but I'm having some problems.

The scenario is the following: When the cell is created I want to load a low quality blurred image (1-2kb) from an URL, before the real image comes in. After the higher quality image is downloaded, I want to show that one. Until now, I've tried these options, but neither one seems to work the way I expect:

1:

    SDWebImageManager *manager = [SDWebImageManager sharedManager];
    [manager downloadImageWithURL:[NSURL URLWithString:lowQualityImageURL]
                          options:0
                         progress:^(NSInteger receivedSize, NSInteger expectedSize) {}
                        completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {

                            if (finished) {
                                cell.pictureView.image = image;
                                [manager downloadImageWithURL:[NSURL URLWithString:highQualityImageURL]
                                                      options:0
                                                     progress:^(NSInteger receivedSize, NSInteger expectedSize) {}
                                                    completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
                                                        if (image && finished) {
                                                            [UIView transitionWithView:cell.pictureView
                                                                              duration:0.1f
                                                                               options:UIViewAnimationOptionTransitionCrossDissolve
                                                                            animations:^{
                                                                                cell.pictureView.image = image;
                                                                            } completion:^(BOOL finished) {

                                                                            }];
                                                        }
                                                    }];
                            }
                        }];

When this code is used, the low quality image seems to be downloaded and showed before the real image, but if the user scrolls fast in the table, he will end up with wrong images for some cells (because of cell reusing - I guess). - Any solution here?

2:

[cell.pictureView sd_setImageWithURL:[NSURL URLWithString:lowQualityImageURL] placeholderImage:[UIImage new] options:SDWebImageRefreshCached completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
            [cell.pictureView sd_setImageWithURL:[NSURL URLWithString:highQualityImageURL] placeholderImage:image options:SDWebImageRefreshCached completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {

            }];
    }];

This approach seems to fix the "wrong image for cell" issue, but most of the cells end up showing their corresponding blurred image istead of the high quality image which is supposed to show.

So, to sum up, do you have an advice about how can I achieve the result I want? (download low quality image -> show it until the high quality image is downloaded -> replace it with high quality image)

LE: When using the 2nd approach I see a weird behaviour. Console output:

  1. thumb set for cell: 1

  2. real image set for cell: 1

  3. thumb set for cell: 2

  4. thumb set for cell: 3

  5. thumb set for cell: 0

  6. real image set for cell: 0

It appears that somehow, some of the downloads get cancelled.

2

There are 2 answers

0
stonycis On BEST ANSWER

I ended up using two UIImageViews, one for each photo, overlapped. When the real (big) image is completely downloaded I smoothly fade the blurred one.

0
AmitP On

Here's a helper function I wrote in Swift using Nuke:

func loadImageWithTwoQualities(lowQualityURL: NSURL, highQualityURL: NSURL, completion: (UIImage) -> () ) {

    Nuke.taskWith(lowQualityURL) {
        completion($0.image!)

        Nuke.taskWith(highQualityURL) {
            completion($0.image!)
        }.resume()

    }.resume()
}

You can use it with any type of image view like so:

let normalImageUrl = NSURL(string: picture)!
let largeImageUrl = NSURL(string: picture + "?type=large")!

loadImageWithTwoQualities(normalImageUrl, highQualityURL: largeImageUrl) { image in
     self.someUIButton.setBackgroundImage(image, forState: .Normal)
}