Possible Duplicate:
Table View with Images, slow load and scroll
I have a UITableView
which downloads images for the UITableViewCells
from a server.
I observed that the tableView scrolls very slowly.
I thought that this might downloading problem, but I have realized that the table still scrolls slowly after download has finished and the image icon size is less.
I searched Google but couldn't find any help.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
btnBack.hidden = FALSE;
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.font = [UIFont fontWithName:@"Noteworthy" size:17.0];
cell.textLabel.font = [UIFont boldSystemFontOfSize:17.0];
cell.textLabel.textColor = [UIColor blackColor];
cell.textLabel.highlightedTextColor = [UIColor blackColor];
}
cell.textLabel.text = [NSString stringWithFormat:@" %@", [test.arrTitle objectAtIndex:indexPath.row]];
NSString *Path;
Path = [NSString stringWithFormat:@"http://%@",[test.arrImages objectAtIndex:indexPath.row]];
NSLog(@"image-->%@",[test.arrImages objectAtIndex:indexPath.row]);
NSString *strImage = Path;
NSURL *url4Image = [NSURL URLWithString:strImage];
NSData *data = [NSData dataWithContentsOfURL:url4Image];
image =[[UIImage alloc] initWithData:data];
cell.imageView.image =image;
[image release];
return cell;
}
It is advisable that you store the images in an array and populate them in your
viewDidLoad
, and then in yourcellForRowAtIndexPath:
just setAs far as the slownesss is concerned, it is because you block the main thread with downloading the URLDATA in your
cellForRowAtIndexPath
method,so while scrolling unless and until the image is not fetched your main thread in which the application runs will get blocked.Scrolling very slow because you are loading images in main thread i.e. synchronously. You can do the same in background thread i.e.asynchronously, have a look at SDWebImage.
While my original answer, below, attempted to solve several key problems associated with asynchronous image retrieval, it is still fundamentally limited. A proper implementation would also make sure that if you scrolled quickly, that the visible cells were prioritized over cells that had scrolled off screen. It would also support cancelation of prior requests (and canceled them for you when appropriate).
While we could add these sorts of capabilities to the below code, it is probably better to adopt an established, proven solution that utilizes the
NSOperationQueue
andNSCache
technologies discussed below, but also addresses the above issues. The easiest solution is to adopt one of the establishedUIImageView
categories that supports asynchronous image retrieval. The AFNetworking and SDWebImage libraries both haveUIImageView
categories that gracefully handle all of these issues.You can use
NSOperationQueue
or GCD to do your lazy loading (see Concurrency Programming Guide for discussion of different asynchronous operations technologies). The former enjoys an advantage that you can specify precisely how many concurrent operations are permissible, which is very important in loading images from the web because many web servers limit how many concurrent requests they will accept from a given client.The basic idea is:
UITableViewCell
is still visible and that it hasn't been dequeued and reused because the cell in question scrolled off the screen. If you don't do that, the wrong image may momentarily show up.You would want to replace your code with something like the following code:
First, define a property for your
NSOperationQueue
that you will use for downloading images, as well as aNSCache
for storing those images:Second, initialize this queue and cache in
viewDidLoad
:Third, your
cellForRowAtIndexPath
might look like:Fourth, and finally, while one might be inclined to write code to purge the cache in low memory situations, it turns out that it does this automatically, so no extra handling is needed here. If you manually simulate a low memory situation in the simulator, you won't see it evict its objects becauseActually,NSCache
doesn't respondUIApplicationDidReceiveMemoryWarningNotification
, but during actual operation, when memory is low, the cache will be purged.NSCache
no longer gracefully responds to low memory situations itself, so you really should add observer for this notification and empty the cache in low memory situations.I might suggest a bunch of other optimizations (e.g. perhaps also caching images into persistent storage to streamline future operations; I actually put all of this logic in my own
AsyncImage
class), but first see if this solves the basic performance issue.As said earlier: don't do any heavy lifting in cellForRowAtIndexPath You can easily get around by using GCD. loading images from a background thread using blocks
You should look to use an
NSOperationQueue
to handle lazy loading of images and a custom tableviewcell. You can get sample example forNSOperationQueue
hereGoogle for tweetie custom tableviewcell That should set you in the right direction.
Apple has a sample project for downloading images in tableViews: LazyTableImages
Write this in your
UITableView
cellForRowAtIndex:
MethodNeed to import
AsyncImageView class
and create Object For that Class