Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to download image asynchronously using blocks?

I want to click a button to start downloading image and to update my UIImageView to new image once it is updated. The problem with my code is that it only downloads stuff, and not updates. It only updates if I click it again. I want it to update the image some time in future, when the image is downloaded. How do I do that?

Edit: I have found the wrong code, changing it a bit helped and it all works. Here comes another question - how do I simplify this code without turning it a mess? It looks excessive.

- (IBAction)getImage
{

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
     ^{
        NSURL *imageURL = [NSURL URLWithString:@"http://example.com/1.jpg"];
        __block NSData *imageData;

         dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
            ^{
                imageData = [NSData dataWithContentsOfURL:imageURL];


                dispatch_sync(dispatch_get_main_queue(), ^{
                                             self.image = [UIImage imageWithData:imageData];
                                         });
                                     });


     });

    self.imageView.image = self.image;
}
like image 708
Dvole Avatar asked Feb 13 '13 19:02

Dvole


2 Answers

You are setting the imageView before the image is done downloading, you need to move the logic into the block. Also there is no reason for you to do an extra dispatch_sync inside of your dispatch_async.

- (IBAction)getImage
{

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
     ^{
        NSURL *imageURL = [NSURL URLWithString:@"http://example.com/1.jpg"];
        NSData *imageData = [NSData dataWithContentsOfURL:imageURL];

        //This is your completion handler
        dispatch_sync(dispatch_get_main_queue(), ^{
             //If self.image is atomic (not declared with nonatomic)
             // you could have set it directly above
             self.image = [UIImage imageWithData:imageData];

             //This needs to be set here now that the image is downloaded
             // and you are back on the main thread
             self.imageView.image = self.image;

         });
     });

     //Any code placed outside of the block will likely
     // be executed before the block finishes.
}
like image 119
Joe Avatar answered Nov 15 '22 09:11

Joe


Check out https://github.com/rs/SDWebImage

I use it to download images in the background with progress notification. It can be added simply to your project using Cocoapods (http://cocoapods.org).

There are several other async image loaders available on Cocoapods and GitHub if that doesn't work for you.

like image 29
Richard Brown Avatar answered Nov 15 '22 08:11

Richard Brown