2

When i'm switching from a view (by clicking on a cell in a table) to a view that displays some images, i'm loading a couple of images from a couple of urls.

I want to display an activity indicator animation while the loading occurs.

I'm doing this loading in viewDidLoad of the new view.

If i'm loading the images synchronously, then (not surprisingly) the animation doesn't work since the request is blocking... If i'm loading the images asynchronously, then (also not surprisingly) the view is opened with blanks instead of images, without waiting for the images to be fetched, which i don't want.

I tried to put all that in the segue code that transforms from the old view to the new one, because i hoped that the view will be switched only after the loading will complete but it didn't matter.

How can I enjoy both worlds? how can i not block the app, display the animation, but transition to the next view only when all the images have been loaded?

mrtubis
  • 170
  • 7

5 Answers5

3

If you don't want to use third party libraries, you can use GCD (Grand central dispatch) like this:

dispatch_queue_t imageLoadingQueue = dispatch_queue_create("imageLoadingQueue", NULL);
// start the loading spinner here
dispatch_async(imageLoadingQueue, ^{
    NSString * urlString = // your URL string here
    NSData * imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
    UIImage * image = [UIImage imageWithData:imageData];
    dispatch_async(dispatch_get_main_queue(), ^{
        // stop the loading spinner here and place the image in your view
    });
});
Aurelien Cobb
  • 435
  • 4
  • 6
  • but if i put this in the viewDidLoad, then the view will be displayed before the images will finish loading. i want the view to be displayed only after fetching the images. – mrtubis Mar 30 '14 at 12:24
  • It won't - as the block (hiding the spinner and placing the image) will only be called after they are loaded. +1 for good answer – Jonathan King Mar 30 '14 at 13:34
  • well, i implemented it, and it displays the new view, with a spinner and then inserts the images. not exactly what i wanted. i want **the transition to the new view happen only after the images were loaded**... – mrtubis Apr 01 '14 at 12:10
  • Sorry for the questions, but just so I understand better: you have a tableview with images, then tapping on one pushes a new viewcontroller with the full size image? but you only want cells to react to a tap if its image is fully loaded? – Aurelien Cobb Apr 03 '14 at 19:12
0

Have a look at AFNetworking and their UIImageView Extension:

setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholderImage;

Asynchronously downloads an image from the specified URL, and sets it once the request is finished.
If the image is cached locally, the image is set immediately, otherwise the specified placeholder image will be set immediately, and then the remote image will be set once the request is finished.

lootsch
  • 1,867
  • 13
  • 21
0

You should take a look at AsyncImageView. It does exactly what you want to do.

You can find it at: https://github.com/nicklockwood/AsyncImageView

ismailgulek
  • 1,029
  • 1
  • 11
  • 8
0

If you don’t want to show certain views while you loading images you can simply hide it, like this self.imageView.hidden = YES; After loading you can set your images, and then set hidden to NO.

If you, for some reason, don’t want to segue to another view, before loading completes, then I think you can make intermediate view, where you’ll download all images, after that segue to your images view, and send that images through prepareForSegue:sender:.

And answer from Aurelien Cobb cleared out how to load images asynchronously.

Alfred Zien
  • 1,025
  • 1
  • 11
  • 31
0

Check SDWebImage (https://github.com/rs/SDWebImage), it has something called prefetcher - which will download the images and save them in cache, after which you will receive a callback, and can transition to the new view. Needless to say that you will have to show a spinner (SVProgressHUD or MBProgressHUD), and stop it once prefetch callback returns.

https://github.com/rs/SDWebImage/blob/master/SDWebImage/SDWebImagePrefetcher.h

/**
 * Assign list of URLs to let SDWebImagePrefetcher to queue the prefetching,
 * currently one image is downloaded at a time,
 * and skips images for failed downloads and proceed to the next image in the list
 *
 * @param urls list of URLs to prefetch
 */
- (void)prefetchURLs:(NSArray *)urls;

To show those images in your imageView, just use setImageWithURL: method (UIImageView+WebCache category).

Cherpak Evgeny
  • 2,659
  • 22
  • 29