Lazy image loading in UITableView iPhone SDK

I need to implement the concept of lazy loading images in my table view so that the user provides text data first and then images.

How can I implement this in my application .. need help .. please

Thanks in advance

Shibin

+2


a source to share


3 answers


What I have created for the project of my works as follows; Extend UITableViewCell class by category in "UITableViewCell + Async.h" (See some examples if you don't know what category is in Obj C)

@interface UITableViewCell (Async)

-(void)loadAsyncImage:(NSString*)url withIndex:(NSInteger)index inWidth:(NSInteger)width inHeight:(NSInteger)height;
-(void)loadAsyncBackground:(NSMutableArray*)parameters;

@end

      

And then in the implementation file "UITableViewCell + Async.m"

#import "UITableViewCell+Async.h"

@implementation UITableViewCell (Async)

-(void)loadAsyncImage:(NSString*)url 
            withIndex:(NSInteger)index 
              inWidth:(NSInteger)width 
             inHeight:(NSInteger)height {

    NSMutableArray* parameters = [NSMutableArray arrayWithCapacity:2];
    [parameters addObject:url];
    [parameters addObject:[NSNumber numberWithInteger:index]];
    [parameters addObject:[NSNumber numberWithInteger:width]];
    [parameters addObject:[NSNumber numberWithInteger:height]];

    self.imageView.tag = index;
    [self performSelectorInBackground:@selector(loadAsyncBackground:) withObject:parameters];

}

-(void)loadAsyncBackground:(NSMutableArray*)parameters {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    NSString* url = [parameters objectAtIndex:0];
    NSInteger index = [[parameters objectAtIndex:1] integerValue];
    NSInteger width = [[parameters objectAtIndex:2] integerValue];
    NSInteger height = [[parameters objectAtIndex:3] integerValue];

    UIImage* image = [Utils getImageResized:url inSize:CGSizeMake(width, height)];

    if (self.tag==index) {
        self.imageView.image = image;
        [self setNeedsLayout];
    }

    [pool release];
}

@end

      

It basically adds the functionality of the UITableViewCell to load the image into a new background thread, resize the image, and bind it to the image view. A tag check is added to see if the cell is still waiting as it might be reused, and another thread for the image might load another image for the reused cell ...



The function in the above code with a signature;

+(UIImage*)getImageResized:(NSString*)url inSize:(CGSize)size;

      

checks the local image cache, downloads the image from the internet if not to the cache, stores it in the local cache, resizes the image to a given size and returns the image, all this is done when the sync (blocking) method is called, Since this is already a background thread, no harm does not block it for this operation. When the method returns an image, it is set in the cell's image view if it still has the same tag (not reused for any other row)

In the cellForRowAtIndexPath method, you can add a new category, and you must do so;

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"......."];
    if (cell == nil) {
................
    }
................
    [cell loadAsyncImage:deal.logo withIndex:indexPath.row inWidth:40 inHeight:40];
................

    return cell;
}

      

+3


a source


Do you mean this



http://developer.apple.com/iphone/library/samplecode/LazyTableImages/Introduction/Intro.html

0


a source


I used ASINetworkQueue for lazy loading.

In the .h file

#import "ASINetworkQueue.h"

      

and define a variable

//array contains url address of images and a variable of ASINetworkQueue;
NSMutableArray *arrImg;
ASINetworkQueue *queue;

      

In the .m file

static int rowNo = 0;
- (void)downloadImages{

    if(queue == nil){
        queue = [[[ASINetworkQueue alloc] init] autorelease];
    }

    for(NSString* urlString in arrImg)
    {
        NSURL *url = [NSURL URLWithString:urlString];
        ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
        [request setDelegate:self];
        [request setDidFinishSelector:@selector(requestDone:)];
        [request setDidFailSelector:@selector(requestWentWrong:)];
        [queue addOperation:request];
    }

    [queue go];

}


- (void)requestDone:(ASIHTTPRequest*)req{   

    for (int i = 0; i < [arrImg count]; i++) {

        NSMutableString *d = [[NSMutableString alloc] init];
        d = [arrImg objectAtIndex:i];

        //comparing the url to get correct row no of cell
        if([[req.url absoluteString] isEqualToString:d]){
            rowNo = i;
            break;
        }
    }

    //creating a cell with rowNo
    NSIndexPath *index = [NSIndexPath indexPathForRow:rowNo inSection:0];

    UITableViewCell *cell = (UITableViewCell *)[roomTable cellForRowAtIndexPath:index];

    UIImageView *v = (UIImageView *)[cell.contentView viewWithTag:10];

    v.image = [UIImage imageWithData:[req responseData]];

    [cell release];
    cell = nil;
    [v release];
    v = nil;
}

- (void)requestWentWrong:(ASIHTTPRequest*)req{

    for (int i = 0; i < [arrImg count]; i++) {

        NSMutableString *d = [[NSMutableString alloc] init];
        d = [arrImg objectAtIndex:i];

        //comparing the url to get correct row no of cell
        if([[req.url absoluteString] isEqualToString:d]){
            rowNo = i;
            break;
        }
    }
    NSLog(@"No data for cell : %d",rowNo);
    NSLog(@"Request returned an error %@",[req error]);
}

      

0


a source







All Articles