Search code examples
objective-cios6objective-c-blocks

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;
}

Solution

  • 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.
    }