Apple recently posted a nice sample called lazyTableLoad. If you study the example you can learn a lot of good techniques for lazy loading images.
We came up with something similar for lazy loading facebook album cover art.
Here are some key elements.
the main item to of interest to note here is that the tableview will display with just the names of the albums , the counts and a placeholder for images still loading. If an album has no images the placeholder will be substituted.
The Facebook fql query is executed in userAlbumArtConneection, which has a return delegate method of
[connDelegate userAlbumArtConnection:self indexPath:_index receivedList:albums];
this method returns the tableView index of the row currently being created and the array of dictionaries of the return value from the fql query.
#import "UserAlbumArtConnection.h"
@implementation UserAlbumArtConnection
@synthesize _index;
- (id) initWithDelegate:(id <UserAlbumArtConnectionDelegate>) delegate
{
if(self = [super init])
{
connDelegate = delegate;
}
return self;
}
// Get the user's facebook friends
- (void) getArt:(NSIndexPath*)indexPath coverPid:(NSString*)coverPid
{
NSLog(@"get art and index %lld", indexPath.row);
_index = indexPath;
NSLog(@"session returned from delegate %lld", [FBSession session].uid);
NSLog(@"got to art");
NSString* fql = [NSString stringWithFormat:
@"select src_small, src_small_width, src_small_height from photo where pid in (select cover_pid from album where cover_pid = %@)", coverPid];
NSDictionary* params = [NSDictionary dictionaryWithObject:fql forKey:@"query"];
[[FBRequest requestWithDelegate:self] call:@"facebook.fql.query" params:params];
}
// FBRequestDelegate
- (void)request:(FBRequest*)request didLoad:(id)result
{
NSLog(@"Art request was ok");
NSArray* albums = result;
// for (NSDictionary *photosDictionary in albums) {
// NSString *cover = [photosDictionary objectForKey:@"src_small"];
// NSLog(@"Query returned src %@", cover);
// }
//for (NSDictionary *photosDictionary in albums) {
// NSString *name = [photosDictionary objectForKey:@"name"];
// [newPhotos addObjectsFromArray:albums];
/*
NSDictionary* album = [albums objectAtIndex:0];
NSString* name = [album objectForKey:@"name"];
NSLog(@"Query returned %@", name);
}
NSString* mycount = [NSString stringWithFormat:@"%d", [albums count]];
NSLog(@"Query returned %@", mycount);
*/
[connDelegate userAlbumArtConnection:self indexPath:_index receivedList:albums];
NSLog(@"and my new index is %lld", _index.row);
}
- (void)request:(FBRequest*)request didFailWithError:(NSError*)error
{
NSLog(@"request failed");
}
@end
Next we look at the tableviewController, myAlbumTableViewController, notice this piece of code which does the lazy loading, using the delgate method, the nslogs are for debugging and will be removed.
- (void)userAlbumArtConnection:(UserAlbumArtConnection *)userAlbumArtConnection indexPath:(NSIndexPath *)index receivedList:(NSArray*)receivedList
{
NSLog(@"did get art pic data");
NSLog(@"get art row and index %u", index.row);
NSLog(@"receivedList count %u", [receivedList count]);
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:index];
// for (NSDictionary *photosDictionary in receivedList) {
// NSString *cover = [photosDictionary objectForKey:@"src_small"];
// NSLog(@"Query returned src %@", cover);
// }
if ([receivedList count] !=0 ) {
NSDictionary *photosDictionary = [receivedList objectAtIndex:0];
NSString *src = [photosDictionary objectForKey:@"src_small"];
NSURL *fcURL = [NSURL URLWithString:src];
NSData *fcData = [NSData dataWithContentsOfURL:fcURL];
UIImage *image = [[UIImage alloc] initWithData:fcData];
CGRect rect = CGRectMake(0.0, 0.0, 80, 80);
UIGraphicsBeginImageContext(rect.size);
[image drawInRect:rect];
cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
//cell.detailTextLabel.text = src;
UIGraphicsEndImageContext();
}
// NSDictionary* album = [receivedList objectAtIndex:0];
}
the full implementation of the view controller is :
@implementation MyAlbumsViewController
@synthesize myAlbums;
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
NSString* mycount = [NSString stringWithFormat:@"%d", [myAlbums count]];
NSLog(@"Query returned %@", mycount);
NSLog(@"session returned %lld", [FBSession session].uid);
// Set the title.
self.title = @"My Albums";
}
- (void)viewWillAppear:(BOOL)animated {
NSString* mycount = [NSString stringWithFormat:@"%d", [myAlbums count]];
NSLog(@"Query returned %@", mycount);
}
- (void)viewDidUnload {
}
-(id) initWithTabBar {
if ([self init]) {
//this is the label on the tab button itself
self.title = @"My Albums";
//use whatever image you want and add it to your project
self.tabBarItem.image = [UIImage imageNamed:@"photos.png"];
// set the long name shown in the navigation bar
self.navigationItem.title=@"My Albums";
}
return self;
}
#pragma mark -
#pragma mark Table view data source methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
tableView.rowHeight = 50.0;
// Only one section.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// As many rows as there are obects in the events array.
return [myAlbums count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
NSDictionary* album = [myAlbums objectAtIndex:indexPath.row];
cell.textLabel.text = [album objectForKey:@"name"];
if ([album objectForKey:@"size"]>0) {
cell.detailTextLabel.text = [NSString stringWithFormat:@" %@ Photos in Album",[album objectForKey:@"size"]];
}else{
cell.detailTextLabel.text = [NSString stringWithFormat:@" No Photos in Album"];
}
[cell.detailTextLabel setFont:[UIFont systemFontOfSize:12.0]];
[cell.detailTextLabel setTextColor:[UIColor darkGrayColor]];
[cell.detailTextLabel setHighlightedTextColor:[UIColor whiteColor]];
[cell.textLabel setFont:[UIFont systemFontOfSize:12.0]];
[cell.textLabel setFont:[UIFont boldSystemFontOfSize:14.0]];
[cell.textLabel setTextColor:[UIColor blackColor]];
[cell.textLabel setHighlightedTextColor:[UIColor whiteColor]];
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
cell.imageView.image = [UIImage imageNamed:@"Placeholder.png"];
userDataConnection = [[UserDataConnection alloc] initWithDelegate:self];
NSLog(@"this is the row in the table view %lld", indexPath.row);
[userDataConnection getUserDataWithIndex:indexPath coverPid:[album objectForKey:@"cover_pid"]];
//cell.imageView.image = event.thumbnail;
return cell;
}
-(NSString *)tableView:(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section
{
return @"My Albums";
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
/**
Handle deletion of an event.
*/
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
}
}
- (void)userDataIndex:(UserDataConnection *)userDataIndex receivedIndex:(NSIndexPath*)receivedIndex coverPid:(NSString*)coverPid
{
userAlbumArtConnection = [[UserAlbumArtConnection alloc] initWithDelegate:self];
[userAlbumArtConnection getArt:receivedIndex coverPid:coverPid];
}
- (void)userAlbumArtConnection:(UserAlbumArtConnection *)userAlbumArtConnection indexPath:(NSIndexPath *)index receivedList:(NSArray*)receivedList
{
NSLog(@"did get art pic data");
NSLog(@"get art row and index %u", index.row);
NSLog(@"receivedList count %u", [receivedList count]);
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:index];
// for (NSDictionary *photosDictionary in receivedList) {
// NSString *cover = [photosDictionary objectForKey:@"src_small"];
// NSLog(@"Query returned src %@", cover);
// }
if ([receivedList count] !=0 ) {
NSDictionary *photosDictionary = [receivedList objectAtIndex:0];
NSString *src = [photosDictionary objectForKey:@"src_small"];
NSURL *fcURL = [NSURL URLWithString:src];
NSData *fcData = [NSData dataWithContentsOfURL:fcURL];
UIImage *image = [[UIImage alloc] initWithData:fcData];
CGRect rect = CGRectMake(0.0, 0.0, 80, 80);
UIGraphicsBeginImageContext(rect.size);
[image drawInRect:rect];
cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
//cell.detailTextLabel.text = src;
UIGraphicsEndImageContext();
}
// NSDictionary* album = [receivedList objectAtIndex:0];
}
#pragma mark -
#pragma mark Memory management
- (void)dealloc {
[super dealloc];
}
@end
Recent Comments