Evgeniy Kleban
Evgeniy Kleban

Reputation: 6940

Loading images for UITableViewCell from URL (need to load them asynchronously)

I have a custom class that parses through an XML and gets URL strings for images (which I store in an array). Then I want to retrieve those strings to load images and display each in a UITableViewCell. Here is my code:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    UILabel *labelText = (UILabel *)[cell viewWithTag:1000];
    labelText.text = [[self.listOfPlaceDetails objectAtIndex:indexPath.row] objectForKey:@"name"];

    NSURL *imageURL = [NSURL URLWithString:[[self.listOfPlaceDetails objectAtIndex:indexPath.row]objectForKey:@"imageCell"]];
    NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
    UIImage *image = [UIImage imageWithData:imageData];
    cell.imageView.image = image;

    return cell;
}

Obviously, when I scroll down the table, the app loads more images, and when the images are loading, the user can't do anything. It looks like the app froze. The images I want to load are not very large (about 8kb). Maybe there is a way I could load and store them in the background? I also want to give more freedom to the user, like scrolling down and viewing cells with text but without an image. Then force the app to load the images for the cells the user is currently viewing.

Is there any way to modify my code or any other solution for proper loading of images from URL strings?

Any advice would be appreciated, thanks.

Upvotes: 2

Views: 2094

Answers (5)

Usman Awan
Usman Awan

Reputation: 1258

You can use the SDWebImage framework to load images asynchronously.

Please follow the link: https://github.com/rs/SDWebImage

Just add the SDWebImage framework to your project and set the other linker flag '-ObjC', to use the framework.

Download link : https://github.com/rs/SDWebImage/releases

Upvotes: 3

Rajjjjjj
Rajjjjjj

Reputation: 434

Use this for asynchronus way of loading imageview

  - (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

 UILabel *labelText = (UILabel *)[cell viewWithTag:1000];
 labelText.text = [[self.listOfPlaceDetails objectAtIndex:indexPath.row] objectForKey:@"name"];


   //get a dispatch queue
   dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//this will start the image loading in bg
dispatch_async(concurrentQueue, ^{
        NSURL *imageURL = [NSURL URLWithString:[[self.listOfPlaceDetails objectAtIndex:indexPath.row]objectForKey:@"imageCell"]];

    NSData *image = [[NSData alloc] initWithContentsOfURL:imageURL];

    //this will set the image when loading is finished
    dispatch_async(dispatch_get_main_queue(), ^{
       cell.imageView.image = [UIImage imageWithData:image];
    });
      });

   return cell;
   }

Upvotes: 2

Ramon
Ramon

Reputation: 1465

Try to load the images asynchronous, so the main thread doesn't block.

Your code would look as follows:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    UILabel *labelText = (UILabel *)[cell viewWithTag:1000];
    labelText.text = [[self.listOfPlaceDetails objectAtIndex:indexPath.row] objectForKey:@"name"];

    NSURL *imageURL = [NSURL URLWithString:[[self.listOfPlaceDetails objectAtIndex:indexPath.row]objectForKey:@"imageCell"]];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
        UIImage *image = [UIImage imageWithData:imageData];

        dispatch_async(dispatch_get_main_queue(), ^{
            cell.imageView.image = image;
        });    
    });

    return cell;
}

Upvotes: 3

rahul
rahul

Reputation: 178

Use NSOperation and NSOperationQueue.A perfect solution for your problem.Use below link to see how it works.

http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues

Or

Use AFNetworking library It also provide a category over UIImageview that download image asynchronously.

Upvotes: 1

jailani
jailani

Reputation: 2270

Download this project and use asynimageveiw in your cell's imageview.. link

Upvotes: 2

Related Questions