I've been using @atebits's ABTableViewCell for a while. For those who are unfamiliar with it, basically it makes tableview scrolling much faster by drawing all the labels and images, instead of allocating UIKit objects (such as UILabels, UIImageView, etc).
Now, I have pretty big UITableViews
and in each cell, there's a small (32x32) user image and a medium (75x75) photo thumbnail. The drawing really helps on making this tableview scroll fast, but I'm still trying to figure what's the best way to fetch these images that are to be drawn inside the cells.
I've looked at Apple's LazyTableView example, but I'm still not sure what's the best way to do this. All I know is the less code/allocation you have in cellForRowAtIndexPath:
, the better it is.
So my images either get downloaded from the server or get retrieved from my CoreDataHelper. My question is: which of the following methods is better to retrieve the cached images?
Use
NSFetchRequest
incellForRowAtIndexPath:
to fetch the cached image (therefore allocating NSFetchRequest instances as the tableview is scrolling).Retain all the cached images from the start within the tableView's datasource, that way I can just fetch them off the (already allocated array in
viewDidLoad:
) datasource in myUITableViewController
. This method clearly takes up more memory since it allocates a bunch of small images, but I'm guessing the scrolling would end up being much smoother.
Can anyone enlight me on this?
(By the way, I want the images to appear as the tableview is scrolling. Waiting for it to stop scrolling to load the images is not an option).
EDIT: loading images from disk
Following the provided answers, I'm now trying to load the images directly from disk (after they get saved, obviously) using the image local path, which is part of the tableview datasource. Here's the code inside the cellForRowAtIndexPath:
method:
NSData *imageData = [NSData dataWithContentsOfFile:imageLocalPath];
UIImage *userImage = [UIImage imageWithData:imageData];
cell.avatarImage = userImage;
It's still not butter smooth (there's a small lag every time a new cell appears (everytime cellForRowAtIndexPath
: is called) Should I be making this call asynchronously? Or is disk reading quick enough and is definitely not the issue here?
EDIT: More details
1. Where are you getting the imageLocalPath?
The image url is part of my dataSource, which is an NSArray allocated in viewDidLoad (cached into CoreData but that shouldn't affect scrolling). The app documents directory path is also retained in viewDidLoad, so the whole filepath is computed in cellForRowAtIndexPath using
NSArray *urlArray = [picURLString componentsSeparatedByString: @"/"];
NSString *filePath = [NSString stringWithFormat:@"%@/%@", documentsPath, [urlArray lastObject];
2. What happens when you run this through shark?
I never used Shark before, tried to use it and apparently iOS 4 no longer supports it. Can you confirm this? When I hit the "Start" button, nothing happens.
3. What FPS are you getting in Instruments on the device?
I'm getting between 25 and 30fps, but it really doesn't look this smooth on the actual screen. Not sure if this means something. I feel like I'm getting 10-15fps. Again, scrolling is smooth between the cells, it's just when the tableview hits a new cell that there's a slight lag (so fast scrolling = many of those small lags every second).