Mikhail Kuznetsov avatar Mikhail Kuznetsov committed 3a96fe4

image loading for table view;

Comments (0)

Files changed (12)

MyShows.xcodeproj/project.pbxproj

 		1829F1921454720F00B98707 /* SVProgressHUD.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 1829F18F1454720F00B98707 /* SVProgressHUD.bundle */; };
 		1829F1931454720F00B98707 /* SVProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 1829F1911454720F00B98707 /* SVProgressHUD.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
 		1829F195145473DD00B98707 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1829F194145473DD00B98707 /* QuartzCore.framework */; };
-		1829F1981454843700B98707 /* AsyncImageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 1829F1971454843700B98707 /* AsyncImageCell.m */; };
 		1866084B144AEC120050B8E1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1866084A144AEC120050B8E1 /* UIKit.framework */; };
 		1866084D144AEC120050B8E1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1866084C144AEC120050B8E1 /* Foundation.framework */; };
 		1866084F144AEC120050B8E1 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1866084E144AEC120050B8E1 /* CoreGraphics.framework */; };
 		186608FF144B150A0050B8E1 /* ASIInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 186608F1144B150A0050B8E1 /* ASIInputStream.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
 		18660900144B150A0050B8E1 /* ASINetworkQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 186608F3144B150A0050B8E1 /* ASINetworkQueue.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
 		18660901144B150A0050B8E1 /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 186608F8144B150A0050B8E1 /* Reachability.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
+		186C58CC145C39F000B0E53E /* TvShow.m in Sources */ = {isa = PBXBuildFile; fileRef = 186C58CB145C39F000B0E53E /* TvShow.m */; };
+		186C58CF145C464500B0E53E /* tv_show_placeholder.png in Resources */ = {isa = PBXBuildFile; fileRef = 186C58CE145C464500B0E53E /* tv_show_placeholder.png */; };
 		18C1DFBB1453136F00687C0B /* LoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18C1DFBA1453136F00687C0B /* LoginViewController.m */; };
 		18C1DFC1145315B500687C0B /* ShowsListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18C1DFC0145315B500687C0B /* ShowsListTableViewController.m */; };
-		18C1DFC41453441400687C0B /* ShowTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 18C1DFC31453441400687C0B /* ShowTableViewCell.m */; };
 		18EE6BAC1452D55F00A4D065 /* NSString+Hash.m in Sources */ = {isa = PBXBuildFile; fileRef = 18EE6BAB1452D55F00A4D065 /* NSString+Hash.m */; };
 /* End PBXBuildFile section */
 
 		1829F1901454720F00B98707 /* SVProgressHUD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVProgressHUD.h; sourceTree = "<group>"; };
 		1829F1911454720F00B98707 /* SVProgressHUD.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SVProgressHUD.m; sourceTree = "<group>"; };
 		1829F194145473DD00B98707 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
-		1829F1961454843700B98707 /* AsyncImageCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AsyncImageCell.h; path = Classes/AsyncImageCell.h; sourceTree = "<group>"; };
-		1829F1971454843700B98707 /* AsyncImageCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AsyncImageCell.m; path = Classes/AsyncImageCell.m; sourceTree = "<group>"; };
 		18660846144AEC120050B8E1 /* MyShows.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MyShows.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		1866084A144AEC120050B8E1 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
 		1866084C144AEC120050B8E1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
 		186608F4144B150A0050B8E1 /* ASIProgressDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIProgressDelegate.h; sourceTree = "<group>"; };
 		186608F7144B150A0050B8E1 /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = "<group>"; };
 		186608F8144B150A0050B8E1 /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Reachability.m; sourceTree = "<group>"; };
+		186C58CA145C39F000B0E53E /* TvShow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TvShow.h; path = Models/TvShow.h; sourceTree = "<group>"; };
+		186C58CB145C39F000B0E53E /* TvShow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TvShow.m; path = Models/TvShow.m; sourceTree = "<group>"; };
+		186C58CE145C464500B0E53E /* tv_show_placeholder.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tv_show_placeholder.png; sourceTree = "<group>"; };
 		18C1DFB91453136F00687C0B /* LoginViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoginViewController.h; sourceTree = "<group>"; };
 		18C1DFBA1453136F00687C0B /* LoginViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoginViewController.m; sourceTree = "<group>"; };
 		18C1DFBF145315B500687C0B /* ShowsListTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShowsListTableViewController.h; sourceTree = "<group>"; };
 		18C1DFC0145315B500687C0B /* ShowsListTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ShowsListTableViewController.m; sourceTree = "<group>"; };
-		18C1DFC21453441300687C0B /* ShowTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ShowTableViewCell.h; path = Classes/ShowTableViewCell.h; sourceTree = "<group>"; };
-		18C1DFC31453441400687C0B /* ShowTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ShowTableViewCell.m; path = Classes/ShowTableViewCell.m; sourceTree = "<group>"; };
 		18EE6BAA1452D55F00A4D065 /* NSString+Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSString+Hash.h"; path = "Categories/NSString+Hash.h"; sourceTree = "<group>"; };
 		18EE6BAB1452D55F00A4D065 /* NSString+Hash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSString+Hash.m"; path = "Categories/NSString+Hash.m"; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 				18C1DFB81453136F00687C0B /* Controllers */,
 				18EE6BA81452D4EE00A4D065 /* Categories */,
 				186608DF144B14D10050B8E1 /* Classes */,
+				186C58CD145C39F500B0E53E /* Models */,
 				18660887144AF4D10050B8E1 /* Libraries */,
 				18660859144AEC120050B8E1 /* AppDelegate.h */,
 				1866085A144AEC120050B8E1 /* AppDelegate.m */,
 		18660884144AEF2D0050B8E1 /* Images */ = {
 			isa = PBXGroup;
 			children = (
+				186C58CE145C464500B0E53E /* tv_show_placeholder.png */,
 				18660885144AEF2D0050B8E1 /* logo-tv.gif */,
 			);
 			path = Images;
 			children = (
 				1829F18B14546E4700B98707 /* ImageManager.h */,
 				1829F18C14546E4700B98707 /* ImageManager.m */,
-				18C1DFC21453441300687C0B /* ShowTableViewCell.h */,
-				18C1DFC31453441400687C0B /* ShowTableViewCell.m */,
 				186608DC144B14920050B8E1 /* MyShowsApi.h */,
 				186608DD144B14930050B8E1 /* MyShowsApi.m */,
-				1829F1961454843700B98707 /* AsyncImageCell.h */,
-				1829F1971454843700B98707 /* AsyncImageCell.m */,
 			);
 			name = Classes;
 			sourceTree = "<group>";
 			path = Reachability;
 			sourceTree = "<group>";
 		};
+		186C58CD145C39F500B0E53E /* Models */ = {
+			isa = PBXGroup;
+			children = (
+				186C58CA145C39F000B0E53E /* TvShow.h */,
+				186C58CB145C39F000B0E53E /* TvShow.m */,
+			);
+			name = Models;
+			sourceTree = "<group>";
+		};
 		18C1DFB81453136F00687C0B /* Controllers */ = {
 			isa = PBXGroup;
 			children = (
 				1866085E144AEC120050B8E1 /* MainStoryboard.storyboard in Resources */,
 				18660886144AEF2D0050B8E1 /* logo-tv.gif in Resources */,
 				1829F1921454720F00B98707 /* SVProgressHUD.bundle in Resources */,
+				186C58CF145C464500B0E53E /* tv_show_placeholder.png in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 				18EE6BAC1452D55F00A4D065 /* NSString+Hash.m in Sources */,
 				18C1DFBB1453136F00687C0B /* LoginViewController.m in Sources */,
 				18C1DFC1145315B500687C0B /* ShowsListTableViewController.m in Sources */,
-				18C1DFC41453441400687C0B /* ShowTableViewCell.m in Sources */,
 				1829F18D14546E4700B98707 /* ImageManager.m in Sources */,
 				1829F1931454720F00B98707 /* SVProgressHUD.m in Sources */,
-				1829F1981454843700B98707 /* AsyncImageCell.m in Sources */,
+				186C58CC145C39F000B0E53E /* TvShow.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

MyShows/Classes/AsyncImageCell.h

-//
-//  AsyncImageCell.h
-//  MyShows
-//
-//  Created by Mikhail Kuznetsov on 23.10.11.
-//  Copyright (c) 2011 __MyCompanyName__. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface AsyncImageCell : UITableViewCell
-
-@property (nonatomic, retain) NSURL *imageURL;
-
-@end

MyShows/Classes/AsyncImageCell.m

-//
-//  AsyncImageCell.m
-//  MyShows
-//
-//  Created by Mikhail Kuznetsov on 23.10.11.
-//  Copyright (c) 2011 __MyCompanyName__. All rights reserved.
-//
-
-#import "AsyncImageCell.h"
-#import "ImageManager.h"
-
-@implementation AsyncImageCell
-
-@synthesize imageURL;
-
-- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
-{
-    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
-    if (self) {
-        // Initialization code
-    }
-    return self;
-}
-
-- (void)setSelected:(BOOL)selected animated:(BOOL)animated
-{
-    [super setSelected:selected animated:animated];
-
-    // Configure the view for the selected state
-}
-
-- (void)drawRect:(CGRect)rect {
-    [super drawRect:rect];
-    if (imageURL) {
-		UIImage *img = [ImageManager loadImage:imageURL];
-		if (img) {
-            self.imageView.image = img;
-		}
-	}
-}
-
-- (void) imageLoaded:(UIImage*)image withURL:(NSURL*)url {
-	if ([imageURL isEqual:url]) {
-		[self setNeedsDisplay];
-	}
-}
-
-@end

MyShows/Classes/ImageManager.h

 #import "ASIDownloadCache.h"
 
 @protocol AsyncImageDelegate <NSObject>
-- (void) imageLoaded:(UIImage *)image withUrl:(NSURL *)url;
+- (void) imageLoaded:(UIImage *)image userInfo:(NSDictionary *) userInfo;
 @end
 
 @interface ImageManager : NSObject {
     
 }
 
-+ (UIImage*)loadImage:(NSURL *)url;
-- (UIImage*)loadImage:(NSURL *)url;
++ (UIImage*)loadImage:(NSURL *)url userInfo:(NSDictionary *) userInfo;
+- (UIImage*)loadImage:(NSURL *)url userInfo:(NSDictionary *) userInfo;
 
 + (void) clearMemoryCache;
 - (void) clearMemoryCache;

MyShows/Classes/ImageManager.m

 	return [NSHomeDirectory() stringByAppendingString:@"/Library/Caches/images/"];
 }
 
-+ (UIImage*)loadImage:(NSURL *)url {
-    return [sharedSingleton loadImage:url];
++ (UIImage*)loadImage:(NSURL *)url userInfo:(NSDictionary *) userInfo {
+    return [sharedSingleton loadImage:url userInfo:userInfo];
 }
 
-- (UIImage*)loadImage:(NSURL *)url {
+- (UIImage*)loadImage:(NSURL *)url userInfo:(NSDictionary *) userInfo {
 	// NSLog(@"url = %@", url);
 	UIImage* img = [loadedImages objectForKey:url];
     if (img) {
     [request setDelegate:self];
     [request setDidFinishSelector:@selector(imageDone:)];
     [request setDidFailSelector:@selector(imageWentWrong:)];
+    [request setUserInfo:userInfo];
     [downloadQueue addOperation:request];
     return nil;
 }
 	
 	[pendingImages removeObject:request.originalURL];
 	[loadedImages setObject:image forKey:request.originalURL];
-	
-	SEL selector = @selector(imageLoaded:withURL:);
+    
+    if ([[request userInfo] objectForKey:@"delegate"]) {
+        id delegate = [[request userInfo] objectForKey:@"delegate"];
         
-    AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
-    UIViewController *controller = [[delegate window] rootViewController]; 
-	
-    if ([controller respondsToSelector:selector]) {
-			[controller performSelector:selector withObject:image withObject:request.originalURL];
+        SEL selector = @selector(imageLoaded:);
+        if ([delegate respondsToSelector:selector]) {
+            [delegate performSelector:selector withObject:image withObject:[request userInfo]];
+        }
     }
 }
 

MyShows/Classes/ShowTableViewCell.h

-//
-//  ShowTableViewCell.h
-//  MyShows
-//
-//  Created by Mikhail Kuznetsov on 22.10.11.
-//  Copyright (c) 2011 __MyCompanyName__. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface ShowTableViewCell : UITableViewCell {
-
-}
-@property (nonatomic, retain) UILabel *ruTitle;
-@property (nonatomic, retain) UILabel *enTitle;
-
--(UILabel *)newLabelWithPrimaryColor:(UIColor *)primaryColor selectedColor:(UIColor *)selectedColor fontSize:(CGFloat)fontSize bold:(BOOL)bold;
-
-@end

MyShows/Classes/ShowTableViewCell.m

-//
-//  ShowTableViewCell.m
-//  MyShows
-//
-//  Created by Mikhail Kuznetsov on 22.10.11.
-//  Copyright (c) 2011 __MyCompanyName__. All rights reserved.
-//
-
-#import "ShowTableViewCell.h"
-
-@implementation ShowTableViewCell
-
-@synthesize ruTitle, enTitle;
-
-- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
-{
-    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
-    if (self) {
-        // Initialization code
-    }
-    return self;
-}
-
-- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
-    self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier];
-    if (self) {
-        // Initialization code
-        UIView *myContentView = self.contentView;
-        
-        self.enTitle = [self newLabelWithPrimaryColor:[UIColor blackColor] selectedColor:[UIColor whiteColor] fontSize:14.0 bold:YES];
-        self.enTitle.textAlignment = UITextAlignmentLeft;
-        [myContentView addSubview:self.enTitle];
-        
-        self.ruTitle = [self newLabelWithPrimaryColor:[UIColor blackColor] selectedColor:[UIColor lightGrayColor] fontSize:10.0 bold:NO];
-        self.ruTitle.textAlignment = UITextAlignmentLeft;
-    }
-    return self;
-}
-
-- (void)setSelected:(BOOL)selected animated:(BOOL)animated
-{
-    [super setSelected:selected animated:animated];
-
-    // Configure the view for the selected state
-}
-
-- (void)layoutSubviews {
-    [super layoutSubviews];
-    
-    CGRect contentRect = self.contentView.bounds;
-    
-    if (!self.editing) {
-        CGFloat boundsX = contentRect.origin.x;
-        CGRect frame;
-        
-        frame = CGRectMake(boundsX + 10, 4, 200, 20);
-        self.enTitle.frame = frame;
-        
-        frame = CGRectMake(boundsX + 10, 28, 200, 14);
-        self.ruTitle.frame = frame;
-    }
-}
-
-- (UILabel *)newLabelWithPrimaryColor:(UIColor *)primaryColor selectedColor:(UIColor *)selectedColor fontSize:(CGFloat)fontSize bold:(BOOL)bold
-{    
-    UIFont *font;
-    if (bold) {
-        font = [UIFont boldSystemFontOfSize:fontSize];
-    } else {
-        font = [UIFont systemFontOfSize:fontSize];
-    }
-    
-	UILabel *newLabel = [[UILabel alloc] initWithFrame:CGRectZero];
-	newLabel.backgroundColor = [UIColor whiteColor];
-	newLabel.opaque = YES;
-	newLabel.textColor = primaryColor;
-	newLabel.highlightedTextColor = selectedColor;
-	newLabel.font = font;
-    
-	return newLabel;
-}
-
-@end

MyShows/Controllers/ShowsListTableViewController.h

 #import "MyShowsApi.h"
 #import "ImageManager.h"
 
+@class TvShow;
+
 @interface ShowsListTableViewController : UITableViewController <ApiDelegate, AsyncImageDelegate> {
     MyShowsApi *api;
     NSMutableArray *shows;
     IBOutlet UITableView *showsTable;
 }
 
-- (void)refreshCellsWithImage:(UIImage*)image fromURL:(NSURL*)url;
+- (UIImage *) loadImage:(TvShow *)currentShow indexPath:(NSIndexPath *) indexPath;
+- (UIImage *)resizeImage:(UIImage *)image;
+- (void) loadImagesForOnscreenRows;
 
 @end

MyShows/Controllers/ShowsListTableViewController.m

 
 #import "ShowsListTableViewController.h"
 #import "SVProgressHUD.h"
-#import "AsyncImageCell.h"
+#import "TvShow.h"
 
 
 @implementation ShowsListTableViewController
         [SVProgressHUD dismiss];
         
         id key;
-        
         NSDictionary *loaded_shows = [[data objectForKey:@"data"] copy];
-        
         NSEnumerator *enumerator = [loaded_shows keyEnumerator];
         
         shows = [[NSMutableArray alloc] init];
         
         while (key = [enumerator nextObject]) {            
             if ([[loaded_shows objectForKey:key] isKindOfClass:[NSDictionary class]]){
-                [shows addObject:[[loaded_shows objectForKey:key] copy]];
+                TvShow *tvShow = [[TvShow alloc] initWithDictionary:[loaded_shows objectForKey:key]];
+                [shows addObject:tvShow];
             }
         }
         NSLog(@"Data stored in array %d, %@", [shows count], shows);
 }
 
 #pragma mark - AsyncImageDelegate
-- (void) imageLoaded:(UIImage *)image withUrl:(NSURL *)url {
-    [self refreshCellsWithImage:image fromURL:url];
+
+- (void) imageLoaded:(UIImage *)image userInfo:(NSDictionary *)userInfo {
+    if ([userInfo objectForKey:@"indexPath"]){
+        image = [self resizeImage:image];
+        [(TvShow *)[shows objectAtIndex:(NSUInteger)[[userInfo objectForKey:@"indexPath"] row]] setImage:image];
+        UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:(NSIndexPath *)[userInfo objectForKey:@"indexPath"]];
+        cell.imageView.image = [(TvShow *)[shows objectAtIndex:(NSUInteger)[[userInfo objectForKey:@"indexPath"] row]] image];
+    }
 }
 
 #pragma mark - Custom methods
 
-- (void) refreshCellsWithImage:(UIImage *)image fromURL:(NSURL *)url {
-    NSArray *cells = [showsTable visibleCells];
+- (UIImage *)resizeImage:(UIImage *)image {
+    if (image.size.width != 48 && image.size.height != 48) {
+        CGSize imageSize = CGSizeMake(48, 48);
+        UIGraphicsBeginImageContext(imageSize);
+        CGRect imageRect = CGRectMake(0.0, 0.0, imageSize.width, imageSize.height);
+        [image drawInRect:imageRect];
+        image = UIGraphicsGetImageFromCurrentImageContext();
+        UIGraphicsEndImageContext();
+    }
+    return image;
+}
 
-    SEL selector = @selector(imageLoaded:withURL:);
-    
-    for (id cell in cells) {
-        if ([cell respondsToSelector:selector]) {
-            [cell performSelector:selector withObject:image withObject:url];
+- (void)loadImagesForOnscreenRows {
+    if ([shows count] > 0) {
+        for (NSIndexPath *indexPath in [self.tableView indexPathsForVisibleRows]) {
+            TvShow *currentShow = [shows objectAtIndex:indexPath.row];
+            if (!currentShow.image) {
+                UIImage *image = [self loadImage:currentShow indexPath:indexPath];
+                if (image) {
+                    [self imageLoaded:image 
+                             userInfo:[[NSDictionary alloc] initWithObjectsAndKeys:
+                                                      indexPath, @"indexPath",
+                                                      nil
+                                       ]];
+                }
+            }
         }
     }
 }
+
+- (UIImage *)loadImage:(TvShow *)currentShow indexPath:(NSIndexPath *) indexPath {
+    return [ImageManager 
+     loadImage:[[NSURL alloc] initWithString:currentShow.imageUrl] 
+     userInfo:[[NSDictionary alloc] initWithObjectsAndKeys:
+               self, @"delegate",
+               indexPath, @"indexPath",
+               nil
+               ]
+     ];
+}
+
 #pragma mark - Table view data source
 
 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
 
 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
-    static NSString *CellIdentifier = @"Cell";
+    static NSString *CellIdentifier = @"TvShowCell";
     
-    AsyncImageCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
+    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
     if (cell == nil) {
-        cell = [[AsyncImageCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
+        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
     }
     
     // Configure the cell...
     cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
+    
+    TvShow *currentShow = [shows objectAtIndex:[indexPath row]];
          
-    NSString *ruTitle = [(NSDictionary *)[shows objectAtIndex:[indexPath row]] objectForKey:@"ruTitle"];
-         
-    if (ruTitle != (id)[NSNull null] && ruTitle != nil && ruTitle.length != 0) {
-        cell.detailTextLabel.text = ruTitle;
+    if (currentShow.ruTitle != (id)[NSNull null] && currentShow.ruTitle != nil && currentShow.ruTitle.length != 0) {
+        cell.detailTextLabel.text = currentShow.ruTitle;
     }
     
-    cell.textLabel.text = [(NSDictionary *)[shows objectAtIndex:[indexPath row]] objectForKey:@"title"];
-        
-    cell.imageURL = [NSURL URLWithString:[(NSDictionary *)[shows objectAtIndex:[indexPath row]] objectForKey:@"image"]];
-    return cell;
-}
-
-- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
-    if (indexPath.row == 0 || indexPath.row % 2 == 0) {
-        cell.backgroundColor = [UIColor colorWithWhite:0.7 alpha:0.1];
+    cell.textLabel.text = currentShow.enTitle;
+    
+    if (!currentShow.image) {
+        UIImage *image;
+        if (self.tableView.dragging == NO && self.tableView.decelerating == NO) {
+            image = [self loadImage:currentShow indexPath:indexPath];
+        }
+        if (image) {
+            image = [self resizeImage:image];
+            currentShow.image = image;
+            cell.imageView.image = image;
+        }
+        else {
+            cell.imageView.image = [UIImage imageNamed:@"tv_show_placeholder.png"];
+        }
     }
+    else {
+        cell.imageView.image = currentShow.image;
+    }
+    
+    return cell;
 }
 
 /*
 
 #pragma mark - Table view delegate
 
+- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
+    if (indexPath.row == 0 || indexPath.row % 2 == 0) {
+        cell.backgroundColor = [UIColor colorWithWhite:0.7 alpha:0.1];
+    }
+}
+
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
 {
     // Navigation logic may go here. Create and push another view controller.
     return 50;
 }
 
+- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
+    if (!decelerate) {
+        [self loadImagesForOnscreenRows];
+    }
+}
+
+- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
+    [self loadImagesForOnscreenRows];
+}
+
 @end

MyShows/Models/TvShow.h

+//
+//  TvShow.h
+//  MyShows
+//
+//  Created by Mikhail Kuznetsov on 29.10.11.
+//  Copyright (c) 2011 __MyCompanyName__. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface TvShow : NSObject {
+    //JSON fields
+    NSString *_ruTitle;
+    NSString *_enTitle;
+    NSString *_imageUrl;
+    
+    //Object fields
+    UIImage *_image;
+}
+
+@property (nonatomic, retain) NSString *ruTitle;
+@property (nonatomic, retain) NSString *enTitle;
+@property (nonatomic, retain) NSString *imageUrl;
+@property (nonatomic, retain) UIImage *image;
+
+- (id)initWithDictionary:(NSDictionary *)data;
+- (NSDictionary *)fieldMap;
+
+@end

MyShows/Models/TvShow.m

+//
+//  TvShow.m
+//  MyShows
+//
+//  Created by Mikhail Kuznetsov on 29.10.11.
+//  Copyright (c) 2011 __MyCompanyName__. All rights reserved.
+//
+
+#import "TvShow.h"
+
+@implementation TvShow
+
+@synthesize ruTitle = _ruTitle;
+@synthesize enTitle = _enTitle;
+@synthesize imageUrl = _imageUrl;
+@synthesize image = _image;
+
+- (id)initWithDictionary:(NSDictionary *)data {
+    self = [super init];
+    if (self) {
+        NSDictionary *fieldMap = [self fieldMap];
+        NSEnumerator *enumerator = [fieldMap keyEnumerator];
+        id key;
+        while (key = [enumerator nextObject]) {
+            if ([data objectForKey:key]) {
+                SEL s = NSSelectorFromString([[NSString alloc] 
+                    initWithFormat:@"set%@%@:", 
+                        [[(NSString *)[fieldMap objectForKey:key] substringToIndex:1]uppercaseString],
+                        [(NSString *)[fieldMap objectForKey:key] substringFromIndex:1]
+                    ]);
+                [self performSelector:s withObject:[data objectForKey:key]];
+            }
+        }
+    }
+    return self;
+}
+
+- (NSDictionary *)fieldMap {
+    // object field - json field
+    return [NSDictionary dictionaryWithObjectsAndKeys:
+            @"ruTitle", @"ruTitle",
+            @"enTitle", @"title",
+            @"imageUrl", @"image",
+            nil];
+}
+
+@end
Add a comment to this file

MyShows/Resources/Images/tv_show_placeholder.png

Added
New image
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.