3

In my app, I receive a list of image URLs to use as thumbnails in my table view. The tableview has a small amount of items, approximately 30, so I want to load all the thumbnails immediately (instead of when they become visible, as they undoubtedly will become visible and I want them fully loaded then).

I want to prioritize the image downloads by index path, so the first index path has priority over the second, which has priority over the third, etc.

However, if I suddenly jump to the end of the table view (which shows, say, index paths 24-29) I want the images for those index paths to become highest priority, so if they jump at the very beginning they won't have to wait for all the others to download first.

How would I go about designing something like this? If it's possible with SDWebImage that'd be great, as I'm comfortable with that, but if not I'm more than fine with creating something from scratch with NSURLSession. (I've looked at SDWebImage, and the SDWebImagePrefetcher looks promising, but doesn't allow priority changing from what I've seen.)

Doug Smith
  • 29,668
  • 57
  • 204
  • 388
  • `SDWebImage` is using an `NSOperation` subclass and `NSOperationQueue`, so you could, hypothetically, provide a public method in `SDWebImageDownloader` to change an operation's queue priority. I don't think that will affect already-executing operations, however; I believe you'd have to cancel and restart those. – jscs Apr 13 '14 at 20:18

1 Answers1

0

I recently had a similar problem, but didn't need to have a priority to load. I can't think of how to change the priority of what is loaded unless you do the loading of thumbnails before loading the tableview. Tableviews load cells as they are needed.

I can think of two options:

  1. If you want all the data loaded and ready before the tableview is even loaded, preemptively load the data in an earlier view controller and save it to be opened in the view controller containing your table view. Then no requests will have to be made by your tableview and everything will appear seamlessly.

  2. The tableview sends each thumbnail request asynchronously and updates the cell as the images arrive on the main thread. You can then cache or save the images after they arrive. But the images won't appear instantly, generally a split second later.

I did option two using NSCache. The value for key "avatar" is the URL of the thumbnail image. This code is located in my - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

if (![teamMember[@"avatar"] isEqualToString:@""]) {
    // check for cached image, use if it exists
    UIImage *cachedImage = [self.imageCache objectForKey:teamMember[@"avatar"]];
    if (cachedImage) {
        cell.memberImage.image = cachedImage;
    }
    //else  retrieve the image from server
    else {
        NSURL *imageURL = [NSURL URLWithString:teamMember[@"avatar"]];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
        // if valid data, create UIImage
        if (imageData) {
            UIImage *image = [UIImage imageWithData:imageData];
            // if valid image, update in tableview asynch
            if (image) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    TeamCommitsCell *updateCell = (id)[tableView cellForRowAtIndexPath:indexPath];
                    // if valid cell, display image and add to cache
                    if (updateCell) {
                        updateCell.memberImage.image = image;
                        [self.imageCache setObject:image forKey:teamMember[@"avatar"]];
                    }
                });
            }
        }
    });
}

}

Inertiatic
  • 1,270
  • 1
  • 9
  • 12