Table View with Images, slow load and scroll
I tried impletmenting about 30 tutorials today and just开发者_如何转开发 cant get anything to work.
My problem is that i load my information via a JSON file, add the data to a NSMutableArray, then use a table to display it all. It works fine when i dont have the images, but when i do its loads very slow and scrolls very sticky. I sorta understand after todays findings that its reloading the images every scroll which is why its slow.
Can someone please break it down and make it easier for me to solve this problem?
Alex
Take a look at Apple's LazyTableImages example. Basically it comes down to
a) reusing your table cells
b) only loading images that are currently visible
You kinda left your problem wide open b/c you weren't specific enough. Performance issues can be related to a bunch of things. Here are a few performance things with tableview cells & images
• Load images on a background thread.
• Reuse cells - don't allocate any more than you need on screen
static NSString *CellIdentifier = @"Cell";
CellClass *cell = (CellClass*)[tv dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) cell = [[[CellClass alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
• Only draw images that are the same size of the cell (ie. if a cell is 44 px high, keep UIimages at 44px). If images are bigger, you might have to process the images after downloading them from the internet.
• Don't use uiimageview in your cell. instead create a custom cell (ie. subclass) and draw the image in your drawRect: function.
You should use asynchronous image retrieval provided by UIImageView
categories found in AFNetworking or SDWebImage. These categories:
are incredibly easy to use (rather than using the
UIImageView
methodsetImage
, instead use one of the categories'setImageWithURL
methods);provide asynchronous image retrieval;
cache the downloaded images with
NSCache
, to make sure you don't have to retrieve images that you just downloaded;ensure that your UI cannot get backlogged downloading images for cells that have scrolled off screen; and
leverage operation queues to constrain the degree of concurrency (rather than using GCD global queues that can result in timeout failures).
I have a class that I call RemoteImageHandler. Here is the .h file:
#import <UIKit/UIKit.h>
@interface RemoteImageHandler : NSObject
- (void)imageForUrl:(NSURL*)url callback:(void(^)(UIImage *image))callback;
+ (RemoteImageHandler *)shared;
@end
And the .m file:
#import "RemoteImageHandler.h"
@interface RemoteImageHandler ()
@property (nonatomic, strong) NSMutableDictionary *imageDictionary;
@end
@implementation RemoteImageHandler
- (void)imageForUrl:(NSURL*)url callback:(void(^)(UIImage *image))callback {
if (!!self.imageDictionary[url]) {
callback(self.imageDictionary[url]);
} else {
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSData * data = [[NSData alloc] initWithContentsOfURL:url];
if (data == nil)
callback(nil);
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:data];
self.imageDictionary[url] = image;
callback(image);
});
});
}
}
+ (TQRemoteImageHandler *)shared {
static TQRemoteImageHandler *shared = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shared = [[self alloc] init];
});
return shared;
}
@end
In my table view, whenever I want an image from a remote location (let's say this is in cellForRowAtIndexPath, I use this:
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath];
[[RemoteImageHandler shared] imageForUrl:someURLCorrespondingToTheImageYouWant callback:^(UIImage *image) {
cell.imageView.image = image;
}];
return cell;
}
精彩评论