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 NSMuta
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
method setImage
, 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;
}
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.