├── .gitignore ├── .gitmodules ├── Demo ├── Classes │ ├── EGOImageLoadingDemoAppDelegate.h │ ├── EGOImageLoadingDemoAppDelegate.m │ ├── ExampleCell.h │ ├── ExampleCell.m │ ├── RootViewController.h │ └── RootViewController.m ├── EGOImageLoadingDemo-Info.plist ├── EGOImageLoadingDemo.xcodeproj │ └── project.pbxproj ├── EGOImageLoadingDemo_Prefix.pch ├── MainWindow.xib ├── RootViewController.xib ├── icon.png ├── main.m └── placeholder.png ├── EGOImageButton ├── EGOImageButton.h └── EGOImageButton.m ├── EGOImageLoader ├── EGOImageLoadConnection.h ├── EGOImageLoadConnection.m ├── EGOImageLoader.h └── EGOImageLoader.m └── EGOImageView ├── EGOImageView.h └── EGOImageView.m /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | *.mode1v3 3 | *.pbxuser 4 | *.DS_Store 5 | *.xcworkspace 6 | xcuserdata 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "EGOCache"] 2 | path = EGOCache 3 | url = git://github.com/enormego/EGOCache.git 4 | -------------------------------------------------------------------------------- /Demo/Classes/EGOImageLoadingDemoAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // EGOImageLoadingDemoAppDelegate.h 3 | // EGOImageLoadingDemo 4 | // 5 | // Created by Shaun Harrison on 10/19/09. 6 | // Copyright enormego 2009. All rights reserved. 7 | // 8 | 9 | @interface EGOImageLoadingDemoAppDelegate : NSObject { 10 | 11 | UIWindow *window; 12 | UINavigationController *navigationController; 13 | } 14 | 15 | @property (nonatomic, retain) IBOutlet UIWindow *window; 16 | @property (nonatomic, retain) IBOutlet UINavigationController *navigationController; 17 | 18 | @end 19 | 20 | -------------------------------------------------------------------------------- /Demo/Classes/EGOImageLoadingDemoAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // EGOImageLoadingDemoAppDelegate.m 3 | // EGOImageLoadingDemo 4 | // 5 | // Created by Shaun Harrison on 10/19/09. 6 | // Copyright enormego 2009. All rights reserved. 7 | // 8 | 9 | #import "EGOImageLoadingDemoAppDelegate.h" 10 | #import "RootViewController.h" 11 | 12 | 13 | @implementation EGOImageLoadingDemoAppDelegate 14 | 15 | @synthesize window; 16 | @synthesize navigationController; 17 | 18 | 19 | #pragma mark - 20 | #pragma mark Application lifecycle 21 | 22 | - (void)applicationDidFinishLaunching:(UIApplication *)application { 23 | 24 | // Override point for customization after app launch 25 | 26 | [window addSubview:[navigationController view]]; 27 | [window makeKeyAndVisible]; 28 | } 29 | 30 | 31 | - (void)applicationWillTerminate:(UIApplication *)application { 32 | // Save data if appropriate 33 | } 34 | 35 | 36 | #pragma mark - 37 | #pragma mark Memory management 38 | 39 | - (void)dealloc { 40 | [navigationController release]; 41 | [window release]; 42 | [super dealloc]; 43 | } 44 | 45 | 46 | @end 47 | 48 | -------------------------------------------------------------------------------- /Demo/Classes/ExampleCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleCell.h 3 | // EGOImageLoadingDemo 4 | // 5 | // Created by Shaun Harrison on 10/19/09. 6 | // Copyright 2009 enormego. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class EGOImageView; 12 | @interface ExampleCell : UITableViewCell { 13 | @private 14 | EGOImageView* imageView; 15 | } 16 | 17 | - (void)setFlickrPhoto:(NSString*)flickrPhoto; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Demo/Classes/ExampleCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleCell.m 3 | // EGOImageLoadingDemo 4 | // 5 | // Created by Shaun Harrison on 10/19/09. 6 | // Copyright 2009 enormego. All rights reserved. 7 | // 8 | 9 | #import "ExampleCell.h" 10 | #import "EGOImageView.h" 11 | #import 12 | 13 | @implementation ExampleCell 14 | 15 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 16 | if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) { 17 | imageView = [[EGOImageView alloc] initWithPlaceholderImage:[UIImage imageNamed:@"placeholder.png"]]; 18 | imageView.frame = CGRectMake(4.0f, 4.0f, 36.0f, 36.0f); 19 | [self.contentView addSubview:imageView]; 20 | } 21 | 22 | return self; 23 | } 24 | 25 | - (void)setFlickrPhoto:(NSString*)flickrPhoto { 26 | imageView.imageURL = [NSURL URLWithString:flickrPhoto]; 27 | } 28 | 29 | - (void)willMoveToSuperview:(UIView *)newSuperview { 30 | [super willMoveToSuperview:newSuperview]; 31 | 32 | if(!newSuperview) { 33 | [imageView cancelImageLoad]; 34 | } 35 | } 36 | 37 | - (void)dealloc { 38 | [imageView release]; 39 | [super dealloc]; 40 | } 41 | 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Demo/Classes/RootViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RootViewController.h 3 | // EGOImageLoadingDemo 4 | // 5 | // Created by Shaun Harrison on 10/19/09. 6 | // Copyright enormego 2009. All rights reserved. 7 | // 8 | 9 | @interface RootViewController : UITableViewController { 10 | @private 11 | NSArray* flickrPhotos; 12 | } 13 | 14 | - (IBAction)clearCache; 15 | - (IBAction)jumpToBottom; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Demo/Classes/RootViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RootViewController.m 3 | // EGOImageLoadingDemo 4 | // 5 | // Created by Shaun Harrison on 10/19/09. 6 | // Copyright enormego 2009. All rights reserved. 7 | // 8 | 9 | #import "RootViewController.h" 10 | #import "ExampleCell.h" 11 | #import "EGOCache.h" 12 | 13 | @implementation RootViewController 14 | 15 | - (void)awakeFromNib { 16 | [super awakeFromNib]; 17 | flickrPhotos = [[NSArray alloc] initWithObjects: 18 | @"http://farm4.static.flickr.com/3483/4017988903_84858e0e6e_s.jpg", 19 | @"http://farm3.static.flickr.com/2436/4015786038_7b530f9cce_s.jpg", 20 | @"http://farm3.static.flickr.com/2643/4025878602_85f7cd1724_s.jpg", 21 | @"http://farm3.static.flickr.com/2494/4011329502_09e6d03b4d_s.jpg", 22 | @"http://farm4.static.flickr.com/3103/4027083130_b187516f48_s.jpg", 23 | @"http://farm3.static.flickr.com/2557/4007449481_59d7a8d848_s.jpg", 24 | @"http://farm4.static.flickr.com/3479/4021202695_381ff2e9bc_s.jpg", 25 | @"http://farm3.static.flickr.com/2598/4010566163_1426fa3389_s.jpg", 26 | @"http://farm3.static.flickr.com/2589/4015601052_ba81c7544b_s.jpg", 27 | @"http://farm3.static.flickr.com/2551/4025950491_20a7615b69_s.jpg", 28 | @"http://farm3.static.flickr.com/2534/4009711388_66ae983c7e_s.jpg", 29 | @"http://farm3.static.flickr.com/2469/4008746903_e90b09241d_s.jpg", 30 | @"http://farm3.static.flickr.com/2432/4025384253_0e521644dd_s.jpg", 31 | @"http://farm3.static.flickr.com/2585/4023151655_d63ecd4025_s.jpg", 32 | @"http://farm3.static.flickr.com/2421/4019640142_7ee56e4b1c_s.jpg", 33 | @"http://farm4.static.flickr.com/3511/4016743839_69370584f3_s.jpg", 34 | @"http://farm3.static.flickr.com/2547/4016748951_f52700aeaa_s.jpg", 35 | @"http://farm4.static.flickr.com/3639/4014434499_b832e04061_s.jpg", 36 | @"http://farm3.static.flickr.com/2190/4018090737_846760e3da_s.jpg", 37 | @"http://farm4.static.flickr.com/3524/4018550718_c4f43a83d0_s.jpg", 38 | @"http://farm4.static.flickr.com/3511/4008358164_a5def010c7_s.jpg", 39 | @"http://farm3.static.flickr.com/2792/4023230831_34b3dfc1ea_s.jpg", 40 | @"http://farm3.static.flickr.com/2438/4021904945_c3706a652a_s.jpg", 41 | @"http://farm3.static.flickr.com/2655/4012063376_5e120a4428_s.jpg", 42 | @"http://farm3.static.flickr.com/2637/4009152189_9fd9034b60_s.jpg", 43 | @"http://farm3.static.flickr.com/2673/4017117612_ae364923b0_s.jpg", 44 | @"http://farm3.static.flickr.com/2495/4020233997_453672b620_s.jpg", 45 | @"http://farm3.static.flickr.com/2586/4014510731_47e9a9b73d_s.jpg", 46 | @"http://farm3.static.flickr.com/2739/4025489621_65264987f8_s.jpg", 47 | @"http://farm3.static.flickr.com/2577/4016420951_def68019dd_s.jpg", 48 | @"http://farm3.static.flickr.com/2500/4026353518_15268c4488_s.jpg", 49 | @"http://farm3.static.flickr.com/2453/4008435378_8e16c06970_s.jpg", 50 | @"http://farm3.static.flickr.com/2745/4026003536_31da429e13_s.jpg", 51 | @"http://farm3.static.flickr.com/2674/4019640830_31e067d771_s.jpg", 52 | @"http://farm3.static.flickr.com/2671/4017291336_b39b72224c_s.jpg", 53 | @"http://farm3.static.flickr.com/2665/4015357692_6d31ab729b_s.jpg", 54 | @"http://farm3.static.flickr.com/2475/4009936307_9a6039aec7_s.jpg", 55 | @"http://farm3.static.flickr.com/2436/4019681008_a5da6093d0_s.jpg", 56 | @"http://farm3.static.flickr.com/2475/4012817856_0e97e6718b_s.jpg", 57 | @"http://farm3.static.flickr.com/2458/4011407242_0073aa2d22_s.jpg", 58 | @"http://farm4.static.flickr.com/3509/4017070907_cea45a8d3a_s.jpg", 59 | @"http://farm4.static.flickr.com/3488/4020067072_7c60a7a60a_s.jpg", 60 | @"http://farm4.static.flickr.com/3503/4011136126_80c3b02986_s.jpg", 61 | @"http://farm3.static.flickr.com/2751/4021887851_c5626ff59a_s.jpg", 62 | @"http://farm3.static.flickr.com/2700/4020348292_856262abc7_s.jpg", 63 | @"http://farm3.static.flickr.com/2620/4010967777_005fdd1867_s.jpg", 64 | @"http://farm4.static.flickr.com/3517/4011690509_4ce02b32cf_s.jpg", 65 | @"http://farm3.static.flickr.com/2454/4012955142_7177f21bf4_s.jpg", 66 | @"http://farm3.static.flickr.com/2538/4014440923_a2b9824628_s.jpg", 67 | @"http://farm3.static.flickr.com/2635/4010051525_74df73bbd7_s.jpg", 68 | @"http://farm3.static.flickr.com/2752/4020781123_baaa208689_s.jpg", 69 | @"http://farm3.static.flickr.com/2622/4014471899_05043a20e3_s.jpg", 70 | @"http://farm3.static.flickr.com/2780/4022823482_26e5530c84_s.jpg", 71 | @"http://farm4.static.flickr.com/3515/4016721686_c828925456_s.jpg", 72 | @"http://farm3.static.flickr.com/2575/4022946879_977e8df918_s.jpg", 73 | @"http://farm3.static.flickr.com/2648/4018130671_8390158767_s.jpg", 74 | @"http://farm3.static.flickr.com/2493/4022863018_6197f81c8d_s.jpg", 75 | @"http://farm4.static.flickr.com/3216/4018267822_e90308c44c_s.jpg", 76 | @"http://farm3.static.flickr.com/2530/4009339944_4d9eb769fc_s.jpg", 77 | @"http://farm3.static.flickr.com/2577/4026000780_e615efd67c_s.jpg", 78 | @"http://farm4.static.flickr.com/3499/4018569395_a4483387b0_s.jpg", 79 | @"http://farm4.static.flickr.com/3509/4019095546_c0f110bc1c_s.jpg", 80 | @"http://farm3.static.flickr.com/2579/4022669316_42065ea829_s.jpg", 81 | @"http://farm3.static.flickr.com/2560/4009382268_7d8812fe98_s.jpg", 82 | @"http://farm3.static.flickr.com/2645/4025740346_03e948466f_s.jpg", 83 | @"http://farm3.static.flickr.com/2800/4021259282_122075711c_s.jpg", 84 | @"http://farm3.static.flickr.com/2430/4019625100_b23147c748_s.jpg", 85 | @"http://farm3.static.flickr.com/2527/4026734100_e52fc21603_s.jpg", 86 | @"http://farm3.static.flickr.com/2635/4020892994_e6101d0f0e_s.jpg", 87 | @"http://farm3.static.flickr.com/2672/4008379269_157e86729e_s.jpg", 88 | @"http://farm3.static.flickr.com/2620/4009289798_bdcf26500a_s.jpg", 89 | @"http://farm3.static.flickr.com/2455/4024701539_9ee5b7fac6_s.jpg", 90 | @"http://farm3.static.flickr.com/2588/4010668107_97207ceb22_s.jpg", 91 | @"http://farm3.static.flickr.com/2459/4023575284_cd01deba10_s.jpg", 92 | @"http://farm3.static.flickr.com/2613/4019518861_5fbd679d61_s.jpg", 93 | @"http://farm3.static.flickr.com/2429/4027017756_f9e6102700_s.jpg", 94 | @"http://farm3.static.flickr.com/2487/4020209639_81a3a2bbc2_s.jpg", 95 | @"http://farm3.static.flickr.com/2670/4013657757_12c694c4ee_s.jpg", 96 | @"http://farm3.static.flickr.com/2804/4019095448_049ef023e3_s.jpg", 97 | @"http://farm3.static.flickr.com/2197/4011866354_0948246520_s.jpg", 98 | @"http://farm3.static.flickr.com/2557/4010652749_1d0c35fabd_s.jpg", 99 | @"http://farm3.static.flickr.com/2543/4010847393_9844b1a37f_s.jpg", 100 | @"http://farm3.static.flickr.com/2724/4021388365_7c739b9b16_s.jpg", 101 | @"http://farm4.static.flickr.com/3484/4018164769_2e68f895dc_s.jpg", 102 | @"http://farm3.static.flickr.com/2643/4020492457_84c4140077_s.jpg", 103 | @"http://farm3.static.flickr.com/2670/4011966914_e1849fda91_s.jpg", 104 | @"http://farm3.static.flickr.com/2653/4015298872_d4ef36c14a_s.jpg", 105 | @"http://farm3.static.flickr.com/2710/4024844149_40dca40cd2_s.jpg", 106 | @"http://farm3.static.flickr.com/2546/4012296861_146d4805df_s.jpg", 107 | nil]; 108 | } 109 | 110 | - (IBAction)clearCache { 111 | [[EGOCache currentCache] clearCache]; 112 | [self.tableView reloadData]; 113 | } 114 | 115 | - (IBAction)jumpToBottom { 116 | [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:flickrPhotos.count-1 inSection:0] 117 | atScrollPosition:UITableViewScrollPositionBottom 118 | animated:NO]; 119 | } 120 | 121 | - (void)didReceiveMemoryWarning { 122 | // Releases the view if it doesn't have a superview. 123 | [super didReceiveMemoryWarning]; 124 | 125 | // Release any cached data, images, etc that aren't in use. 126 | } 127 | 128 | - (void)viewDidUnload { 129 | // Release anything that can be recreated in viewDidLoad or on demand. 130 | // e.g. self.myOutlet = nil; 131 | } 132 | 133 | 134 | #pragma mark Table view methods 135 | 136 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 137 | return 1; 138 | } 139 | 140 | 141 | // Customize the number of rows in the table view. 142 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 143 | return flickrPhotos.count; 144 | } 145 | 146 | 147 | // Customize the appearance of table view cells. 148 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 149 | 150 | static NSString *CellIdentifier = @"ExampleCell"; 151 | 152 | ExampleCell *cell = (ExampleCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 153 | if (cell == nil) { 154 | cell = [[[ExampleCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 155 | } 156 | 157 | // Configure the cell. 158 | [cell setFlickrPhoto:[flickrPhotos objectAtIndex:indexPath.row]]; 159 | 160 | return cell; 161 | } 162 | 163 | - (void)dealloc { 164 | [flickrPhotos release]; 165 | [super dealloc]; 166 | } 167 | 168 | 169 | @end 170 | 171 | -------------------------------------------------------------------------------- /Demo/EGOImageLoadingDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | com.yourcompany.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | NSMainNibFile 28 | MainWindow 29 | 30 | 31 | -------------------------------------------------------------------------------- /Demo/EGOImageLoadingDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 45; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1D3623260D0F684500981E51 /* EGOImageLoadingDemoAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* EGOImageLoadingDemoAppDelegate.m */; }; 11 | 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; 12 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 13 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 14 | 2826AB4D108D4295007FBD1D /* EGOCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 2826AB0F108D4295007FBD1D /* EGOCache.m */; }; 15 | 2826AB4E108D4295007FBD1D /* EGOImageButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 2826AB12108D4295007FBD1D /* EGOImageButton.m */; }; 16 | 2826AB4F108D4295007FBD1D /* EGOImageLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 2826AB15108D4295007FBD1D /* EGOImageLoader.m */; }; 17 | 2826AB50108D4295007FBD1D /* EGOImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2826AB18108D4295007FBD1D /* EGOImageView.m */; }; 18 | 2826AB8E108D5160007FBD1D /* ExampleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 2826AB8D108D5160007FBD1D /* ExampleCell.m */; }; 19 | 2826AB90108D5258007FBD1D /* placeholder.png in Resources */ = {isa = PBXBuildFile; fileRef = 2826AB8F108D5258007FBD1D /* placeholder.png */; }; 20 | 2826ABDB108D56AE007FBD1D /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 2826ABDA108D56AE007FBD1D /* icon.png */; }; 21 | 287464C9136C1CD800DB4329 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 287464C8136C1CD800DB4329 /* QuartzCore.framework */; }; 22 | 2892E4100DC94CBA00A64D0F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */; }; 23 | 28AD73600D9D9599002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD735F0D9D9599002E5188 /* MainWindow.xib */; }; 24 | 28BBA36B10C62E3300081AB5 /* EGOImageLoadConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 28BBA36A10C62E3300081AB5 /* EGOImageLoadConnection.m */; }; 25 | 28C286E10D94DF7D0034E888 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28C286E00D94DF7D0034E888 /* RootViewController.m */; }; 26 | 28F335F11007B36200424DE2 /* RootViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28F335F01007B36200424DE2 /* RootViewController.xib */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 31 | 1D3623240D0F684500981E51 /* EGOImageLoadingDemoAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EGOImageLoadingDemoAppDelegate.h; sourceTree = ""; }; 32 | 1D3623250D0F684500981E51 /* EGOImageLoadingDemoAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EGOImageLoadingDemoAppDelegate.m; sourceTree = ""; }; 33 | 1D6058910D05DD3D006BFB54 /* EGOImageLoadingDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EGOImageLoadingDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 35 | 2826AB0E108D4295007FBD1D /* EGOCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EGOCache.h; sourceTree = ""; }; 36 | 2826AB0F108D4295007FBD1D /* EGOCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EGOCache.m; sourceTree = ""; }; 37 | 2826AB11108D4295007FBD1D /* EGOImageButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EGOImageButton.h; sourceTree = ""; }; 38 | 2826AB12108D4295007FBD1D /* EGOImageButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EGOImageButton.m; sourceTree = ""; }; 39 | 2826AB14108D4295007FBD1D /* EGOImageLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EGOImageLoader.h; sourceTree = ""; }; 40 | 2826AB15108D4295007FBD1D /* EGOImageLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EGOImageLoader.m; sourceTree = ""; }; 41 | 2826AB17108D4295007FBD1D /* EGOImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EGOImageView.h; sourceTree = ""; }; 42 | 2826AB18108D4295007FBD1D /* EGOImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EGOImageView.m; sourceTree = ""; }; 43 | 2826AB8C108D5160007FBD1D /* ExampleCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleCell.h; sourceTree = ""; }; 44 | 2826AB8D108D5160007FBD1D /* ExampleCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExampleCell.m; sourceTree = ""; }; 45 | 2826AB8F108D5258007FBD1D /* placeholder.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = placeholder.png; sourceTree = ""; }; 46 | 2826ABDA108D56AE007FBD1D /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = ""; }; 47 | 287464C8136C1CD800DB4329 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 48 | 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 49 | 28A0AAE50D9B0CCF005BE974 /* EGOImageLoadingDemo_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EGOImageLoadingDemo_Prefix.pch; sourceTree = ""; }; 50 | 28AD735F0D9D9599002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; 51 | 28BBA36910C62E3300081AB5 /* EGOImageLoadConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EGOImageLoadConnection.h; sourceTree = ""; }; 52 | 28BBA36A10C62E3300081AB5 /* EGOImageLoadConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EGOImageLoadConnection.m; sourceTree = ""; }; 53 | 28C286DF0D94DF7D0034E888 /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = ""; }; 54 | 28C286E00D94DF7D0034E888 /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = ""; }; 55 | 28F335F01007B36200424DE2 /* RootViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RootViewController.xib; sourceTree = ""; }; 56 | 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 57 | 8D1107310486CEB800E47090 /* EGOImageLoadingDemo-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "EGOImageLoadingDemo-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = ""; }; 58 | /* End PBXFileReference section */ 59 | 60 | /* Begin PBXFrameworksBuildPhase section */ 61 | 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { 62 | isa = PBXFrameworksBuildPhase; 63 | buildActionMask = 2147483647; 64 | files = ( 65 | 287464C9136C1CD800DB4329 /* QuartzCore.framework in Frameworks */, 66 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 67 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, 68 | 2892E4100DC94CBA00A64D0F /* CoreGraphics.framework in Frameworks */, 69 | ); 70 | runOnlyForDeploymentPostprocessing = 0; 71 | }; 72 | /* End PBXFrameworksBuildPhase section */ 73 | 74 | /* Begin PBXGroup section */ 75 | 080E96DDFE201D6D7F000001 /* Classes */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 28C286DF0D94DF7D0034E888 /* RootViewController.h */, 79 | 28C286E00D94DF7D0034E888 /* RootViewController.m */, 80 | 1D3623240D0F684500981E51 /* EGOImageLoadingDemoAppDelegate.h */, 81 | 1D3623250D0F684500981E51 /* EGOImageLoadingDemoAppDelegate.m */, 82 | 2826AB8C108D5160007FBD1D /* ExampleCell.h */, 83 | 2826AB8D108D5160007FBD1D /* ExampleCell.m */, 84 | ); 85 | path = Classes; 86 | sourceTree = ""; 87 | }; 88 | 19C28FACFE9D520D11CA2CBB /* Products */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 1D6058910D05DD3D006BFB54 /* EGOImageLoadingDemo.app */, 92 | ); 93 | name = Products; 94 | sourceTree = ""; 95 | }; 96 | 2826AAB2108D4280007FBD1D /* EGOImageLoading */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 2826AAB3108D4295007FBD1D /* EGOCache */, 100 | 2826AB10108D4295007FBD1D /* EGOImageButton */, 101 | 2826AB13108D4295007FBD1D /* EGOImageLoader */, 102 | 2826AB16108D4295007FBD1D /* EGOImageView */, 103 | ); 104 | name = EGOImageLoading; 105 | sourceTree = ""; 106 | }; 107 | 2826AAB3108D4295007FBD1D /* EGOCache */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 2826AB0E108D4295007FBD1D /* EGOCache.h */, 111 | 2826AB0F108D4295007FBD1D /* EGOCache.m */, 112 | ); 113 | name = EGOCache; 114 | path = ../EGOCache; 115 | sourceTree = SOURCE_ROOT; 116 | }; 117 | 2826AB10108D4295007FBD1D /* EGOImageButton */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 2826AB11108D4295007FBD1D /* EGOImageButton.h */, 121 | 2826AB12108D4295007FBD1D /* EGOImageButton.m */, 122 | ); 123 | name = EGOImageButton; 124 | path = ../EGOImageButton; 125 | sourceTree = SOURCE_ROOT; 126 | }; 127 | 2826AB13108D4295007FBD1D /* EGOImageLoader */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | 2826AB14108D4295007FBD1D /* EGOImageLoader.h */, 131 | 2826AB15108D4295007FBD1D /* EGOImageLoader.m */, 132 | 28BBA36910C62E3300081AB5 /* EGOImageLoadConnection.h */, 133 | 28BBA36A10C62E3300081AB5 /* EGOImageLoadConnection.m */, 134 | ); 135 | name = EGOImageLoader; 136 | path = ../EGOImageLoader; 137 | sourceTree = SOURCE_ROOT; 138 | }; 139 | 2826AB16108D4295007FBD1D /* EGOImageView */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | 2826AB17108D4295007FBD1D /* EGOImageView.h */, 143 | 2826AB18108D4295007FBD1D /* EGOImageView.m */, 144 | ); 145 | name = EGOImageView; 146 | path = ../EGOImageView; 147 | sourceTree = SOURCE_ROOT; 148 | }; 149 | 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | 2826AAB2108D4280007FBD1D /* EGOImageLoading */, 153 | 080E96DDFE201D6D7F000001 /* Classes */, 154 | 29B97315FDCFA39411CA2CEA /* Other Sources */, 155 | 29B97317FDCFA39411CA2CEA /* Resources */, 156 | 29B97323FDCFA39411CA2CEA /* Frameworks */, 157 | 19C28FACFE9D520D11CA2CBB /* Products */, 158 | ); 159 | name = CustomTemplate; 160 | sourceTree = ""; 161 | }; 162 | 29B97315FDCFA39411CA2CEA /* Other Sources */ = { 163 | isa = PBXGroup; 164 | children = ( 165 | 28A0AAE50D9B0CCF005BE974 /* EGOImageLoadingDemo_Prefix.pch */, 166 | 29B97316FDCFA39411CA2CEA /* main.m */, 167 | ); 168 | name = "Other Sources"; 169 | sourceTree = ""; 170 | }; 171 | 29B97317FDCFA39411CA2CEA /* Resources */ = { 172 | isa = PBXGroup; 173 | children = ( 174 | 2826ABDA108D56AE007FBD1D /* icon.png */, 175 | 2826AB8F108D5258007FBD1D /* placeholder.png */, 176 | 28F335F01007B36200424DE2 /* RootViewController.xib */, 177 | 28AD735F0D9D9599002E5188 /* MainWindow.xib */, 178 | 8D1107310486CEB800E47090 /* EGOImageLoadingDemo-Info.plist */, 179 | ); 180 | name = Resources; 181 | sourceTree = ""; 182 | }; 183 | 29B97323FDCFA39411CA2CEA /* Frameworks */ = { 184 | isa = PBXGroup; 185 | children = ( 186 | 287464C8136C1CD800DB4329 /* QuartzCore.framework */, 187 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, 188 | 1D30AB110D05D00D00671497 /* Foundation.framework */, 189 | 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */, 190 | ); 191 | name = Frameworks; 192 | sourceTree = ""; 193 | }; 194 | /* End PBXGroup section */ 195 | 196 | /* Begin PBXNativeTarget section */ 197 | 1D6058900D05DD3D006BFB54 /* EGOImageLoadingDemo */ = { 198 | isa = PBXNativeTarget; 199 | buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "EGOImageLoadingDemo" */; 200 | buildPhases = ( 201 | 1D60588D0D05DD3D006BFB54 /* Resources */, 202 | 1D60588E0D05DD3D006BFB54 /* Sources */, 203 | 1D60588F0D05DD3D006BFB54 /* Frameworks */, 204 | ); 205 | buildRules = ( 206 | ); 207 | dependencies = ( 208 | ); 209 | name = EGOImageLoadingDemo; 210 | productName = EGOImageLoadingDemo; 211 | productReference = 1D6058910D05DD3D006BFB54 /* EGOImageLoadingDemo.app */; 212 | productType = "com.apple.product-type.application"; 213 | }; 214 | /* End PBXNativeTarget section */ 215 | 216 | /* Begin PBXProject section */ 217 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 218 | isa = PBXProject; 219 | buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "EGOImageLoadingDemo" */; 220 | compatibilityVersion = "Xcode 3.1"; 221 | developmentRegion = English; 222 | hasScannedForEncodings = 1; 223 | knownRegions = ( 224 | English, 225 | Japanese, 226 | French, 227 | German, 228 | en, 229 | ); 230 | mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; 231 | projectDirPath = ""; 232 | projectRoot = ""; 233 | targets = ( 234 | 1D6058900D05DD3D006BFB54 /* EGOImageLoadingDemo */, 235 | ); 236 | }; 237 | /* End PBXProject section */ 238 | 239 | /* Begin PBXResourcesBuildPhase section */ 240 | 1D60588D0D05DD3D006BFB54 /* Resources */ = { 241 | isa = PBXResourcesBuildPhase; 242 | buildActionMask = 2147483647; 243 | files = ( 244 | 28AD73600D9D9599002E5188 /* MainWindow.xib in Resources */, 245 | 28F335F11007B36200424DE2 /* RootViewController.xib in Resources */, 246 | 2826AB90108D5258007FBD1D /* placeholder.png in Resources */, 247 | 2826ABDB108D56AE007FBD1D /* icon.png in Resources */, 248 | ); 249 | runOnlyForDeploymentPostprocessing = 0; 250 | }; 251 | /* End PBXResourcesBuildPhase section */ 252 | 253 | /* Begin PBXSourcesBuildPhase section */ 254 | 1D60588E0D05DD3D006BFB54 /* Sources */ = { 255 | isa = PBXSourcesBuildPhase; 256 | buildActionMask = 2147483647; 257 | files = ( 258 | 1D60589B0D05DD56006BFB54 /* main.m in Sources */, 259 | 1D3623260D0F684500981E51 /* EGOImageLoadingDemoAppDelegate.m in Sources */, 260 | 28C286E10D94DF7D0034E888 /* RootViewController.m in Sources */, 261 | 2826AB4D108D4295007FBD1D /* EGOCache.m in Sources */, 262 | 2826AB4E108D4295007FBD1D /* EGOImageButton.m in Sources */, 263 | 2826AB4F108D4295007FBD1D /* EGOImageLoader.m in Sources */, 264 | 2826AB50108D4295007FBD1D /* EGOImageView.m in Sources */, 265 | 2826AB8E108D5160007FBD1D /* ExampleCell.m in Sources */, 266 | 28BBA36B10C62E3300081AB5 /* EGOImageLoadConnection.m in Sources */, 267 | ); 268 | runOnlyForDeploymentPostprocessing = 0; 269 | }; 270 | /* End PBXSourcesBuildPhase section */ 271 | 272 | /* Begin XCBuildConfiguration section */ 273 | 1D6058940D05DD3E006BFB54 /* Debug */ = { 274 | isa = XCBuildConfiguration; 275 | buildSettings = { 276 | ALWAYS_SEARCH_USER_PATHS = NO; 277 | COPY_PHASE_STRIP = NO; 278 | GCC_DYNAMIC_NO_PIC = NO; 279 | GCC_OPTIMIZATION_LEVEL = 0; 280 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 281 | GCC_PREFIX_HEADER = EGOImageLoadingDemo_Prefix.pch; 282 | INFOPLIST_FILE = "EGOImageLoadingDemo-Info.plist"; 283 | PRODUCT_NAME = EGOImageLoadingDemo; 284 | SDKROOT = iphoneos; 285 | }; 286 | name = Debug; 287 | }; 288 | 1D6058950D05DD3E006BFB54 /* Release */ = { 289 | isa = XCBuildConfiguration; 290 | buildSettings = { 291 | ALWAYS_SEARCH_USER_PATHS = NO; 292 | COPY_PHASE_STRIP = YES; 293 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 294 | GCC_PREFIX_HEADER = EGOImageLoadingDemo_Prefix.pch; 295 | INFOPLIST_FILE = "EGOImageLoadingDemo-Info.plist"; 296 | PRODUCT_NAME = EGOImageLoadingDemo; 297 | SDKROOT = iphoneos; 298 | }; 299 | name = Release; 300 | }; 301 | C01FCF4F08A954540054247B /* Debug */ = { 302 | isa = XCBuildConfiguration; 303 | buildSettings = { 304 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 305 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 306 | GCC_C_LANGUAGE_STANDARD = c99; 307 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 308 | GCC_WARN_UNUSED_VARIABLE = YES; 309 | IPHONEOS_DEPLOYMENT_TARGET = 4.0; 310 | PREBINDING = NO; 311 | SDKROOT = iphoneos3.1; 312 | }; 313 | name = Debug; 314 | }; 315 | C01FCF5008A954540054247B /* Release */ = { 316 | isa = XCBuildConfiguration; 317 | buildSettings = { 318 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 319 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 320 | GCC_C_LANGUAGE_STANDARD = c99; 321 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 322 | GCC_WARN_UNUSED_VARIABLE = YES; 323 | IPHONEOS_DEPLOYMENT_TARGET = 4.0; 324 | PREBINDING = NO; 325 | SDKROOT = iphoneos3.1; 326 | }; 327 | name = Release; 328 | }; 329 | /* End XCBuildConfiguration section */ 330 | 331 | /* Begin XCConfigurationList section */ 332 | 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "EGOImageLoadingDemo" */ = { 333 | isa = XCConfigurationList; 334 | buildConfigurations = ( 335 | 1D6058940D05DD3E006BFB54 /* Debug */, 336 | 1D6058950D05DD3E006BFB54 /* Release */, 337 | ); 338 | defaultConfigurationIsVisible = 0; 339 | defaultConfigurationName = Release; 340 | }; 341 | C01FCF4E08A954540054247B /* Build configuration list for PBXProject "EGOImageLoadingDemo" */ = { 342 | isa = XCConfigurationList; 343 | buildConfigurations = ( 344 | C01FCF4F08A954540054247B /* Debug */, 345 | C01FCF5008A954540054247B /* Release */, 346 | ); 347 | defaultConfigurationIsVisible = 0; 348 | defaultConfigurationName = Release; 349 | }; 350 | /* End XCConfigurationList section */ 351 | }; 352 | rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; 353 | } 354 | -------------------------------------------------------------------------------- /Demo/EGOImageLoadingDemo_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'EGOImageLoadingDemo' target in the 'EGOImageLoadingDemo' project 3 | // 4 | #import 5 | 6 | #ifndef __IPHONE_3_0 7 | #warning "This project uses features only available in iPhone SDK 3.0 and later." 8 | #endif 9 | 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /Demo/MainWindow.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 784 5 | 10B504 6 | 731 7 | 1038.2 8 | 437.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 62 12 | 13 | 14 | YES 15 | 16 | 17 | 18 | YES 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | YES 23 | 24 | YES 25 | 26 | 27 | YES 28 | 29 | 30 | 31 | YES 32 | 33 | IBFilesOwner 34 | 35 | 36 | IBFirstResponder 37 | 38 | 39 | 40 | 41 | 1316 42 | 43 | {320, 480} 44 | 45 | 1 46 | MSAxIDEAA 47 | 48 | NO 49 | NO 50 | 51 | 52 | 53 | 54 | 55 | 56 | 256 57 | {0, 0} 58 | NO 59 | YES 60 | YES 61 | 62 | 63 | YES 64 | 65 | 66 | 67 | 68 | Jump to Bottom 69 | 1 70 | 71 | 72 | Clear Cache 73 | 1 74 | 75 | 76 | 77 | RootViewController 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | YES 86 | 87 | 88 | delegate 89 | 90 | 91 | 92 | 4 93 | 94 | 95 | 96 | window 97 | 98 | 99 | 100 | 5 101 | 102 | 103 | 104 | navigationController 105 | 106 | 107 | 108 | 15 109 | 110 | 111 | 112 | clearCache 113 | 114 | 115 | 116 | 17 117 | 118 | 119 | 120 | jumpToBottom 121 | 122 | 123 | 124 | 19 125 | 126 | 127 | 128 | 129 | YES 130 | 131 | 0 132 | 133 | 134 | 135 | 136 | 137 | 2 138 | 139 | 140 | YES 141 | 142 | 143 | 144 | 145 | -1 146 | 147 | 148 | File's Owner 149 | 150 | 151 | 3 152 | 153 | 154 | 155 | 156 | -2 157 | 158 | 159 | 160 | 161 | 9 162 | 163 | 164 | YES 165 | 166 | 167 | 168 | 169 | 170 | 171 | 11 172 | 173 | 174 | 175 | 176 | 13 177 | 178 | 179 | YES 180 | 181 | 182 | 183 | 184 | 185 | 14 186 | 187 | 188 | YES 189 | 190 | 191 | 192 | 193 | 194 | 195 | 16 196 | 197 | 198 | 199 | 200 | 18 201 | 202 | 203 | 204 | 205 | 206 | 207 | YES 208 | 209 | YES 210 | -1.CustomClassName 211 | -2.CustomClassName 212 | 11.IBPluginDependency 213 | 13.CustomClassName 214 | 13.IBPluginDependency 215 | 16.IBPluginDependency 216 | 18.IBPluginDependency 217 | 2.IBAttributePlaceholdersKey 218 | 2.IBEditorWindowLastContentRect 219 | 2.IBPluginDependency 220 | 3.CustomClassName 221 | 3.IBPluginDependency 222 | 9.IBEditorWindowLastContentRect 223 | 9.IBPluginDependency 224 | 225 | 226 | YES 227 | UIApplication 228 | UIResponder 229 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 230 | RootViewController 231 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 232 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 233 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 234 | 235 | YES 236 | 237 | 238 | YES 239 | 240 | 241 | {{673, 376}, {320, 480}} 242 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 243 | EGOImageLoadingDemoAppDelegate 244 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 245 | {{500, 276}, {320, 480}} 246 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 247 | 248 | 249 | 250 | YES 251 | 252 | 253 | YES 254 | 255 | 256 | 257 | 258 | YES 259 | 260 | 261 | YES 262 | 263 | 264 | 265 | 19 266 | 267 | 268 | 269 | YES 270 | 271 | EGOImageLoadingDemoAppDelegate 272 | NSObject 273 | 274 | YES 275 | 276 | YES 277 | navigationController 278 | window 279 | 280 | 281 | YES 282 | UINavigationController 283 | UIWindow 284 | 285 | 286 | 287 | IBProjectSource 288 | Classes/EGOImageLoadingDemoAppDelegate.h 289 | 290 | 291 | 292 | RootViewController 293 | UITableViewController 294 | 295 | YES 296 | 297 | YES 298 | clearCache 299 | jumpToBottom 300 | 301 | 302 | YES 303 | id 304 | id 305 | 306 | 307 | 308 | IBProjectSource 309 | Classes/RootViewController.h 310 | 311 | 312 | 313 | 314 | YES 315 | 316 | NSObject 317 | 318 | IBFrameworkSource 319 | Foundation.framework/Headers/NSError.h 320 | 321 | 322 | 323 | NSObject 324 | 325 | IBFrameworkSource 326 | Foundation.framework/Headers/NSFileManager.h 327 | 328 | 329 | 330 | NSObject 331 | 332 | IBFrameworkSource 333 | Foundation.framework/Headers/NSKeyValueCoding.h 334 | 335 | 336 | 337 | NSObject 338 | 339 | IBFrameworkSource 340 | Foundation.framework/Headers/NSKeyValueObserving.h 341 | 342 | 343 | 344 | NSObject 345 | 346 | IBFrameworkSource 347 | Foundation.framework/Headers/NSKeyedArchiver.h 348 | 349 | 350 | 351 | NSObject 352 | 353 | IBFrameworkSource 354 | Foundation.framework/Headers/NSNetServices.h 355 | 356 | 357 | 358 | NSObject 359 | 360 | IBFrameworkSource 361 | Foundation.framework/Headers/NSObject.h 362 | 363 | 364 | 365 | NSObject 366 | 367 | IBFrameworkSource 368 | Foundation.framework/Headers/NSPort.h 369 | 370 | 371 | 372 | NSObject 373 | 374 | IBFrameworkSource 375 | Foundation.framework/Headers/NSRunLoop.h 376 | 377 | 378 | 379 | NSObject 380 | 381 | IBFrameworkSource 382 | Foundation.framework/Headers/NSStream.h 383 | 384 | 385 | 386 | NSObject 387 | 388 | IBFrameworkSource 389 | Foundation.framework/Headers/NSThread.h 390 | 391 | 392 | 393 | NSObject 394 | 395 | IBFrameworkSource 396 | Foundation.framework/Headers/NSURL.h 397 | 398 | 399 | 400 | NSObject 401 | 402 | IBFrameworkSource 403 | Foundation.framework/Headers/NSURLConnection.h 404 | 405 | 406 | 407 | NSObject 408 | 409 | IBFrameworkSource 410 | Foundation.framework/Headers/NSXMLParser.h 411 | 412 | 413 | 414 | NSObject 415 | 416 | IBFrameworkSource 417 | UIKit.framework/Headers/UIAccessibility.h 418 | 419 | 420 | 421 | NSObject 422 | 423 | IBFrameworkSource 424 | UIKit.framework/Headers/UINibLoading.h 425 | 426 | 427 | 428 | NSObject 429 | 430 | IBFrameworkSource 431 | UIKit.framework/Headers/UIResponder.h 432 | 433 | 434 | 435 | UIApplication 436 | UIResponder 437 | 438 | IBFrameworkSource 439 | UIKit.framework/Headers/UIApplication.h 440 | 441 | 442 | 443 | UIBarButtonItem 444 | UIBarItem 445 | 446 | IBFrameworkSource 447 | UIKit.framework/Headers/UIBarButtonItem.h 448 | 449 | 450 | 451 | UIBarItem 452 | NSObject 453 | 454 | IBFrameworkSource 455 | UIKit.framework/Headers/UIBarItem.h 456 | 457 | 458 | 459 | UINavigationBar 460 | UIView 461 | 462 | IBFrameworkSource 463 | UIKit.framework/Headers/UINavigationBar.h 464 | 465 | 466 | 467 | UINavigationController 468 | UIViewController 469 | 470 | IBFrameworkSource 471 | UIKit.framework/Headers/UINavigationController.h 472 | 473 | 474 | 475 | UINavigationItem 476 | NSObject 477 | 478 | 479 | 480 | UIResponder 481 | NSObject 482 | 483 | 484 | 485 | UISearchBar 486 | UIView 487 | 488 | IBFrameworkSource 489 | UIKit.framework/Headers/UISearchBar.h 490 | 491 | 492 | 493 | UISearchDisplayController 494 | NSObject 495 | 496 | IBFrameworkSource 497 | UIKit.framework/Headers/UISearchDisplayController.h 498 | 499 | 500 | 501 | UITableViewController 502 | UIViewController 503 | 504 | IBFrameworkSource 505 | UIKit.framework/Headers/UITableViewController.h 506 | 507 | 508 | 509 | UIView 510 | 511 | IBFrameworkSource 512 | UIKit.framework/Headers/UITextField.h 513 | 514 | 515 | 516 | UIView 517 | UIResponder 518 | 519 | IBFrameworkSource 520 | UIKit.framework/Headers/UIView.h 521 | 522 | 523 | 524 | UIViewController 525 | 526 | 527 | 528 | UIViewController 529 | 530 | IBFrameworkSource 531 | UIKit.framework/Headers/UITabBarController.h 532 | 533 | 534 | 535 | UIViewController 536 | UIResponder 537 | 538 | IBFrameworkSource 539 | UIKit.framework/Headers/UIViewController.h 540 | 541 | 542 | 543 | UIWindow 544 | UIView 545 | 546 | IBFrameworkSource 547 | UIKit.framework/Headers/UIWindow.h 548 | 549 | 550 | 551 | 552 | 0 553 | 554 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 555 | 556 | 557 | 558 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 559 | 560 | 561 | YES 562 | EGOImageLoadingDemo.xcodeproj 563 | 3 564 | 3.1 565 | 566 | 567 | -------------------------------------------------------------------------------- /Demo/RootViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 784 5 | 10A405 6 | 732 7 | 1031 8 | 432.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 62 12 | 13 | 14 | YES 15 | 16 | 17 | 18 | YES 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | YES 23 | 24 | YES 25 | 26 | 27 | YES 28 | 29 | 30 | 31 | YES 32 | 33 | IBFilesOwner 34 | 35 | 36 | IBFirstResponder 37 | 38 | 39 | 40 | 274 41 | {320, 247} 42 | 43 | 44 | 3 45 | MQA 46 | 47 | NO 48 | YES 49 | NO 50 | NO 51 | 1 52 | 0 53 | YES 54 | 44 55 | 22 56 | 22 57 | 58 | 59 | 60 | 61 | YES 62 | 63 | 64 | view 65 | 66 | 67 | 68 | 3 69 | 70 | 71 | 72 | dataSource 73 | 74 | 75 | 76 | 4 77 | 78 | 79 | 80 | delegate 81 | 82 | 83 | 84 | 5 85 | 86 | 87 | 88 | 89 | YES 90 | 91 | 0 92 | 93 | 94 | 95 | 96 | 97 | -1 98 | 99 | 100 | File's Owner 101 | 102 | 103 | -2 104 | 105 | 106 | 107 | 108 | 2 109 | 110 | 111 | 112 | 113 | 114 | 115 | YES 116 | 117 | YES 118 | -1.CustomClassName 119 | -2.CustomClassName 120 | 2.IBEditorWindowLastContentRect 121 | 2.IBPluginDependency 122 | 123 | 124 | YES 125 | RootViewController 126 | UIResponder 127 | {{0, 598}, {320, 247}} 128 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 129 | 130 | 131 | 132 | YES 133 | 134 | 135 | YES 136 | 137 | 138 | 139 | 140 | YES 141 | 142 | 143 | YES 144 | 145 | 146 | 147 | 5 148 | 149 | 150 | 151 | YES 152 | 153 | RootViewController 154 | UITableViewController 155 | 156 | IBProjectSource 157 | Classes/RootViewController.h 158 | 159 | 160 | 161 | 162 | YES 163 | 164 | NSObject 165 | 166 | IBFrameworkSource 167 | Foundation.framework/Headers/NSError.h 168 | 169 | 170 | 171 | NSObject 172 | 173 | IBFrameworkSource 174 | Foundation.framework/Headers/NSFileManager.h 175 | 176 | 177 | 178 | NSObject 179 | 180 | IBFrameworkSource 181 | Foundation.framework/Headers/NSKeyValueCoding.h 182 | 183 | 184 | 185 | NSObject 186 | 187 | IBFrameworkSource 188 | Foundation.framework/Headers/NSKeyValueObserving.h 189 | 190 | 191 | 192 | NSObject 193 | 194 | IBFrameworkSource 195 | Foundation.framework/Headers/NSKeyedArchiver.h 196 | 197 | 198 | 199 | NSObject 200 | 201 | IBFrameworkSource 202 | Foundation.framework/Headers/NSNetServices.h 203 | 204 | 205 | 206 | NSObject 207 | 208 | IBFrameworkSource 209 | Foundation.framework/Headers/NSObject.h 210 | 211 | 212 | 213 | NSObject 214 | 215 | IBFrameworkSource 216 | Foundation.framework/Headers/NSPort.h 217 | 218 | 219 | 220 | NSObject 221 | 222 | IBFrameworkSource 223 | Foundation.framework/Headers/NSRunLoop.h 224 | 225 | 226 | 227 | NSObject 228 | 229 | IBFrameworkSource 230 | Foundation.framework/Headers/NSStream.h 231 | 232 | 233 | 234 | NSObject 235 | 236 | IBFrameworkSource 237 | Foundation.framework/Headers/NSThread.h 238 | 239 | 240 | 241 | NSObject 242 | 243 | IBFrameworkSource 244 | Foundation.framework/Headers/NSURL.h 245 | 246 | 247 | 248 | NSObject 249 | 250 | IBFrameworkSource 251 | Foundation.framework/Headers/NSURLConnection.h 252 | 253 | 254 | 255 | NSObject 256 | 257 | IBFrameworkSource 258 | Foundation.framework/Headers/NSXMLParser.h 259 | 260 | 261 | 262 | NSObject 263 | 264 | IBFrameworkSource 265 | UIKit.framework/Headers/UIAccessibility.h 266 | 267 | 268 | 269 | NSObject 270 | 271 | IBFrameworkSource 272 | UIKit.framework/Headers/UINibLoading.h 273 | 274 | 275 | 276 | NSObject 277 | 278 | IBFrameworkSource 279 | UIKit.framework/Headers/UIResponder.h 280 | 281 | 282 | 283 | UIResponder 284 | NSObject 285 | 286 | 287 | 288 | UIScrollView 289 | UIView 290 | 291 | IBFrameworkSource 292 | UIKit.framework/Headers/UIScrollView.h 293 | 294 | 295 | 296 | UISearchBar 297 | UIView 298 | 299 | IBFrameworkSource 300 | UIKit.framework/Headers/UISearchBar.h 301 | 302 | 303 | 304 | UISearchDisplayController 305 | NSObject 306 | 307 | IBFrameworkSource 308 | UIKit.framework/Headers/UISearchDisplayController.h 309 | 310 | 311 | 312 | UITableView 313 | UIScrollView 314 | 315 | IBFrameworkSource 316 | UIKit.framework/Headers/UITableView.h 317 | 318 | 319 | 320 | UITableViewController 321 | UIViewController 322 | 323 | IBFrameworkSource 324 | UIKit.framework/Headers/UITableViewController.h 325 | 326 | 327 | 328 | UIView 329 | 330 | IBFrameworkSource 331 | UIKit.framework/Headers/UITextField.h 332 | 333 | 334 | 335 | UIView 336 | UIResponder 337 | 338 | IBFrameworkSource 339 | UIKit.framework/Headers/UIView.h 340 | 341 | 342 | 343 | UIViewController 344 | 345 | IBFrameworkSource 346 | UIKit.framework/Headers/UINavigationController.h 347 | 348 | 349 | 350 | UIViewController 351 | 352 | IBFrameworkSource 353 | UIKit.framework/Headers/UITabBarController.h 354 | 355 | 356 | 357 | UIViewController 358 | UIResponder 359 | 360 | IBFrameworkSource 361 | UIKit.framework/Headers/UIViewController.h 362 | 363 | 364 | 365 | 366 | 0 367 | 368 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 369 | 370 | 371 | 372 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 373 | 374 | 375 | YES 376 | EGOImageLoadingDemo.xcodeproj 377 | 3 378 | 3.1 379 | 380 | 381 | -------------------------------------------------------------------------------- /Demo/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enormego/EGOImageLoading/4f4e6a626ef518d59dd38f5e69b835365f5a4830/Demo/icon.png -------------------------------------------------------------------------------- /Demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // EGOImageLoadingDemo 4 | // 5 | // Created by Shaun Harrison on 10/19/09. 6 | // Copyright enormego 2009. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) { 12 | 13 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 14 | int retVal = UIApplicationMain(argc, argv, nil, nil); 15 | [pool release]; 16 | return retVal; 17 | } 18 | -------------------------------------------------------------------------------- /Demo/placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enormego/EGOImageLoading/4f4e6a626ef518d59dd38f5e69b835365f5a4830/Demo/placeholder.png -------------------------------------------------------------------------------- /EGOImageButton/EGOImageButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // EGOImageButton.h 3 | // EGOImageLoading 4 | // 5 | // Created by Shaun Harrison on 9/30/09. 6 | // Copyright (c) 2009-2010 enormego 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | #import 28 | #import "EGOImageLoader.h" 29 | 30 | @protocol EGOImageButtonDelegate; 31 | @interface EGOImageButton : UIButton { 32 | @private 33 | NSURL* imageURL; 34 | UIImage* placeholderImage; 35 | id delegate; 36 | } 37 | 38 | - (id)initWithPlaceholderImage:(UIImage*)anImage; // delegate:nil 39 | - (id)initWithPlaceholderImage:(UIImage*)anImage delegate:(id)aDelegate; 40 | 41 | - (void)cancelImageLoad; 42 | 43 | @property(nonatomic,retain) NSURL* imageURL; 44 | @property(nonatomic,retain) UIImage* placeholderImage; 45 | @property(nonatomic,assign) id delegate; 46 | @end 47 | 48 | @protocol EGOImageButtonDelegate 49 | @optional 50 | - (void)imageButtonLoadedImage:(EGOImageButton*)imageButton; 51 | - (void)imageButtonFailedToLoadImage:(EGOImageButton*)imageButton error:(NSError*)error; 52 | @end -------------------------------------------------------------------------------- /EGOImageButton/EGOImageButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // EGOImageButton.m 3 | // EGOImageLoading 4 | // 5 | // Created by Shaun Harrison on 9/30/09. 6 | // Copyright (c) 2009-2010 enormego 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | #import "EGOImageButton.h" 28 | 29 | 30 | @implementation EGOImageButton 31 | @synthesize imageURL, placeholderImage, delegate; 32 | 33 | - (id)initWithPlaceholderImage:(UIImage*)anImage { 34 | return [self initWithPlaceholderImage:anImage delegate:nil]; 35 | } 36 | 37 | - (id)initWithPlaceholderImage:(UIImage*)anImage delegate:(id)aDelegate { 38 | if((self = [super initWithFrame:CGRectZero])) { 39 | self.placeholderImage = anImage; 40 | self.delegate = aDelegate; 41 | [self setImage:self.placeholderImage forState:UIControlStateNormal]; 42 | } 43 | 44 | return self; 45 | } 46 | 47 | - (void)setImageURL:(NSURL *)aURL { 48 | if(imageURL) { 49 | [[EGOImageLoader sharedImageLoader] removeObserver:self forURL:imageURL]; 50 | [imageURL release]; 51 | imageURL = nil; 52 | } 53 | 54 | if(!aURL) { 55 | [self setImage:self.placeholderImage forState:UIControlStateNormal]; 56 | imageURL = nil; 57 | return; 58 | } else { 59 | imageURL = [aURL retain]; 60 | } 61 | 62 | UIImage* anImage = [[EGOImageLoader sharedImageLoader] imageForURL:aURL shouldLoadWithObserver:self]; 63 | 64 | if(anImage) { 65 | [self setImage:anImage forState:UIControlStateNormal]; 66 | } else { 67 | [self setImage:self.placeholderImage forState:UIControlStateNormal]; 68 | } 69 | } 70 | 71 | #pragma mark - 72 | #pragma mark Image loading 73 | 74 | - (void)cancelImageLoad { 75 | [[EGOImageLoader sharedImageLoader] cancelLoadForURL:self.imageURL]; 76 | [[EGOImageLoader sharedImageLoader] removeObserver:self forURL:self.imageURL]; 77 | } 78 | 79 | - (void)imageLoaderDidLoad:(NSNotification*)notification { 80 | if(![[[notification userInfo] objectForKey:@"imageURL"] isEqual:self.imageURL]) return; 81 | 82 | UIImage* anImage = [[notification userInfo] objectForKey:@"image"]; 83 | [self setImage:anImage forState:UIControlStateNormal]; 84 | [self setNeedsDisplay]; 85 | 86 | if([self.delegate respondsToSelector:@selector(imageButtonLoadedImage:)]) { 87 | [self.delegate imageButtonLoadedImage:self]; 88 | } 89 | } 90 | 91 | - (void)imageLoaderDidFailToLoad:(NSNotification*)notification { 92 | if(![[[notification userInfo] objectForKey:@"imageURL"] isEqual:self.imageURL]) return; 93 | 94 | if([self.delegate respondsToSelector:@selector(imageButtonFailedToLoadImage:error:)]) { 95 | [self.delegate imageButtonFailedToLoadImage:self error:[[notification userInfo] objectForKey:@"error"]]; 96 | } 97 | } 98 | 99 | #pragma mark - 100 | - (void)dealloc { 101 | [[EGOImageLoader sharedImageLoader] removeObserver:self]; 102 | 103 | self.imageURL = nil; 104 | self.placeholderImage = nil; 105 | [super dealloc]; 106 | } 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /EGOImageLoader/EGOImageLoadConnection.h: -------------------------------------------------------------------------------- 1 | // 2 | // EGOImageLoadConnection.h 3 | // EGOImageLoading 4 | // 5 | // Created by Shaun Harrison on 12/1/09. 6 | // Copyright (c) 2009-2010 enormego 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | #import 28 | 29 | @protocol EGOImageLoadConnectionDelegate; 30 | 31 | @interface EGOImageLoadConnection : NSObject { 32 | @private 33 | NSURL* _imageURL; 34 | NSURLResponse* _response; 35 | NSMutableData* _responseData; 36 | NSURLConnection* _connection; 37 | NSTimeInterval _timeoutInterval; 38 | 39 | id _delegate; 40 | } 41 | 42 | - (id)initWithImageURL:(NSURL*)aURL delegate:(id)delegate; 43 | 44 | - (void)start; 45 | - (void)cancel; 46 | 47 | @property(nonatomic,readonly) NSData* responseData; 48 | @property(nonatomic,readonly,getter=imageURL) NSURL* imageURL; 49 | 50 | @property(nonatomic,retain) NSURLResponse* response; 51 | @property(nonatomic,assign) id delegate; 52 | 53 | @property(nonatomic,assign) NSTimeInterval timeoutInterval; // Default is 30 seconds 54 | 55 | #if __EGOIL_USE_BLOCKS 56 | @property(nonatomic,readonly) NSMutableDictionary* handlers; 57 | #endif 58 | 59 | @end 60 | 61 | @protocol EGOImageLoadConnectionDelegate 62 | - (void)imageLoadConnectionDidFinishLoading:(EGOImageLoadConnection *)connection; 63 | - (void)imageLoadConnection:(EGOImageLoadConnection *)connection didFailWithError:(NSError *)error; 64 | @end -------------------------------------------------------------------------------- /EGOImageLoader/EGOImageLoadConnection.m: -------------------------------------------------------------------------------- 1 | // 2 | // EGOImageLoadConnection.m 3 | // EGOImageLoading 4 | // 5 | // Created by Shaun Harrison on 12/1/09. 6 | // Copyright (c) 2009-2010 enormego 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | #import "EGOImageLoadConnection.h" 28 | 29 | 30 | @implementation EGOImageLoadConnection 31 | @synthesize imageURL=_imageURL, response=_response, delegate=_delegate, timeoutInterval=_timeoutInterval; 32 | 33 | #if __EGOIL_USE_BLOCKS 34 | @synthesize handlers; 35 | #endif 36 | 37 | - (id)initWithImageURL:(NSURL*)aURL delegate:(id)delegate { 38 | if((self = [super init])) { 39 | _imageURL = [aURL retain]; 40 | self.delegate = delegate; 41 | _responseData = [[NSMutableData alloc] init]; 42 | self.timeoutInterval = 30; 43 | 44 | #if __EGOIL_USE_BLOCKS 45 | handlers = [[NSMutableDictionary alloc] init]; 46 | #endif 47 | } 48 | 49 | return self; 50 | } 51 | 52 | - (void)start { 53 | NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:self.imageURL 54 | cachePolicy:NSURLRequestReturnCacheDataElseLoad 55 | timeoutInterval:self.timeoutInterval]; 56 | [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"]; 57 | _connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES]; 58 | [request release]; 59 | } 60 | 61 | - (void)cancel { 62 | [_connection cancel]; 63 | } 64 | 65 | - (NSData*)responseData { 66 | return _responseData; 67 | } 68 | 69 | - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 70 | if(connection != _connection) return; 71 | [_responseData appendData:data]; 72 | } 73 | 74 | - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 75 | if(connection != _connection) return; 76 | self.response = response; 77 | } 78 | 79 | - (void)connectionDidFinishLoading:(NSURLConnection *)connection { 80 | if(connection != _connection) return; 81 | 82 | if([self.delegate respondsToSelector:@selector(imageLoadConnectionDidFinishLoading:)]) { 83 | [self.delegate imageLoadConnectionDidFinishLoading:self]; 84 | } 85 | } 86 | 87 | - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 88 | if(connection != _connection) return; 89 | 90 | if([self.delegate respondsToSelector:@selector(imageLoadConnection:didFailWithError:)]) { 91 | [self.delegate imageLoadConnection:self didFailWithError:error]; 92 | } 93 | } 94 | 95 | 96 | - (void)dealloc { 97 | self.response = nil; 98 | self.delegate = nil; 99 | 100 | #if __EGOIL_USE_BLOCKS 101 | [handlers release], handlers = nil; 102 | #endif 103 | 104 | [_connection release]; 105 | [_imageURL release]; 106 | [_responseData release]; 107 | [super dealloc]; 108 | } 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /EGOImageLoader/EGOImageLoader.h: -------------------------------------------------------------------------------- 1 | // 2 | // EGOImageLoader.h 3 | // EGOImageLoading 4 | // 5 | // Created by Shaun Harrison on 9/15/09. 6 | // Copyright (c) 2009-2010 enormego 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | #import 28 | 29 | #ifndef __EGOIL_USE_BLOCKS 30 | #define __EGOIL_USE_BLOCKS 0 31 | #endif 32 | 33 | #ifndef __EGOIL_USE_NOTIF 34 | #define __EGOIL_USE_NOTIF 1 35 | #endif 36 | 37 | @protocol EGOImageLoaderObserver; 38 | @interface EGOImageLoader : NSObject/**/ { 39 | @private 40 | NSDictionary* _currentConnections; 41 | NSMutableDictionary* currentConnections; 42 | #if __EGOIL_USE_BLOCKS 43 | dispatch_queue_t _operationQueue; 44 | #endif 45 | 46 | NSLock* connectionsLock; 47 | } 48 | 49 | + (EGOImageLoader*)sharedImageLoader; 50 | 51 | - (BOOL)isLoadingImageURL:(NSURL*)aURL; 52 | 53 | #if __EGOIL_USE_NOTIF 54 | - (void)loadImageForURL:(NSURL*)aURL observer:(id)observer; 55 | - (UIImage*)imageForURL:(NSURL*)aURL shouldLoadWithObserver:(id)observer; 56 | 57 | - (void)removeObserver:(id)observer; 58 | - (void)removeObserver:(id)observer forURL:(NSURL*)aURL; 59 | #endif 60 | 61 | #if __EGOIL_USE_BLOCKS 62 | - (void)loadImageForURL:(NSURL*)aURL completion:(void (^)(UIImage* image, NSURL* imageURL, NSError* error))completion; 63 | - (void)loadImageForURL:(NSURL*)aURL style:(NSString*)style styler:(UIImage* (^)(UIImage* image))styler completion:(void (^)(UIImage* image, NSURL* imageURL, NSError* error))completion; 64 | #endif 65 | 66 | - (BOOL)hasLoadedImageURL:(NSURL*)aURL; 67 | - (void)cancelLoadForURL:(NSURL*)aURL; 68 | 69 | - (void)clearCacheForURL:(NSURL*)aURL; 70 | - (void)clearCacheForURL:(NSURL*)aURL style:(NSString*)style; 71 | 72 | @property(nonatomic,retain) NSDictionary* currentConnections; 73 | @end 74 | 75 | @protocol EGOImageLoaderObserver 76 | @optional 77 | - (void)imageLoaderDidLoad:(NSNotification*)notification; // Object will be EGOImageLoader, userInfo will contain imageURL and image 78 | - (void)imageLoaderDidFailToLoad:(NSNotification*)notification; // Object will be EGOImageLoader, userInfo will contain error 79 | @end 80 | -------------------------------------------------------------------------------- /EGOImageLoader/EGOImageLoader.m: -------------------------------------------------------------------------------- 1 | // 2 | // EGOImageLoader.m 3 | // EGOImageLoading 4 | // 5 | // Created by Shaun Harrison on 9/15/09. 6 | // Copyright (c) 2009-2010 enormego 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | #import "EGOImageLoader.h" 28 | #import "EGOImageLoadConnection.h" 29 | #import "EGOCache.h" 30 | 31 | static EGOImageLoader* __imageLoader; 32 | 33 | inline static NSString* keyForURL(NSURL* url, NSString* style) { 34 | if(style) { 35 | return [NSString stringWithFormat:@"EGOImageLoader-%u-%u", [[url description] hash], [style hash]]; 36 | } else { 37 | return [NSString stringWithFormat:@"EGOImageLoader-%u", [[url description] hash]]; 38 | } 39 | } 40 | 41 | #if __EGOIL_USE_BLOCKS 42 | #define kNoStyle @"EGOImageLoader-nostyle" 43 | #define kCompletionsKey @"completions" 44 | #define kStylerKey @"styler" 45 | #define kStylerQueue _operationQueue 46 | #define kCompletionsQueue dispatch_get_main_queue() 47 | #endif 48 | 49 | #if __EGOIL_USE_NOTIF 50 | #define kImageNotificationLoaded(s) [@"kEGOImageLoaderNotificationLoaded-" stringByAppendingString:keyForURL(s, nil)] 51 | #define kImageNotificationLoadFailed(s) [@"kEGOImageLoaderNotificationLoadFailed-" stringByAppendingString:keyForURL(s, nil)] 52 | #endif 53 | 54 | @interface EGOImageLoader () 55 | #if __EGOIL_USE_BLOCKS 56 | - (void)handleCompletionsForConnection:(EGOImageLoadConnection*)connection image:(UIImage*)image error:(NSError*)error; 57 | #endif 58 | @end 59 | 60 | @implementation EGOImageLoader 61 | @synthesize currentConnections=_currentConnections; 62 | 63 | + (EGOImageLoader*)sharedImageLoader { 64 | @synchronized(self) { 65 | if(!__imageLoader) { 66 | __imageLoader = [[[self class] alloc] init]; 67 | } 68 | } 69 | 70 | return __imageLoader; 71 | } 72 | 73 | - (id)init { 74 | if((self = [super init])) { 75 | connectionsLock = [[NSLock alloc] init]; 76 | currentConnections = [[NSMutableDictionary alloc] init]; 77 | 78 | #if __EGOIL_USE_BLOCKS 79 | _operationQueue = dispatch_queue_create("com.enormego.EGOImageLoader",NULL); 80 | dispatch_queue_t priority = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0); 81 | dispatch_set_target_queue(priority, _operationQueue); 82 | #endif 83 | } 84 | 85 | return self; 86 | } 87 | 88 | - (EGOImageLoadConnection*)loadingConnectionForURL:(NSURL*)aURL { 89 | EGOImageLoadConnection* connection = [[self.currentConnections objectForKey:aURL] retain]; 90 | if(!connection) return nil; 91 | else return [connection autorelease]; 92 | } 93 | 94 | - (void)cleanUpConnection:(EGOImageLoadConnection*)connection { 95 | if(!connection.imageURL) return; 96 | 97 | connection.delegate = nil; 98 | 99 | [connectionsLock lock]; 100 | [currentConnections removeObjectForKey:connection.imageURL]; 101 | self.currentConnections = [[currentConnections copy] autorelease]; 102 | [connectionsLock unlock]; 103 | } 104 | 105 | - (void)clearCacheForURL:(NSURL*)aURL { 106 | [self clearCacheForURL:aURL style:nil]; 107 | } 108 | 109 | - (void)clearCacheForURL:(NSURL*)aURL style:(NSString*)style { 110 | [[EGOCache currentCache] removeCacheForKey:keyForURL(aURL, style)]; 111 | } 112 | 113 | - (BOOL)isLoadingImageURL:(NSURL*)aURL { 114 | return [self loadingConnectionForURL:aURL] ? YES : NO; 115 | } 116 | 117 | - (void)cancelLoadForURL:(NSURL*)aURL { 118 | EGOImageLoadConnection* connection = [self loadingConnectionForURL:aURL]; 119 | [NSObject cancelPreviousPerformRequestsWithTarget:connection selector:@selector(start) object:nil]; 120 | [connection cancel]; 121 | [self cleanUpConnection:connection]; 122 | } 123 | 124 | - (EGOImageLoadConnection*)loadImageForURL:(NSURL*)aURL { 125 | EGOImageLoadConnection* connection; 126 | 127 | if((connection = [self loadingConnectionForURL:aURL])) { 128 | return connection; 129 | } else { 130 | connection = [[EGOImageLoadConnection alloc] initWithImageURL:aURL delegate:self]; 131 | 132 | [connectionsLock lock]; 133 | [currentConnections setObject:connection forKey:aURL]; 134 | self.currentConnections = [[currentConnections copy] autorelease]; 135 | [connectionsLock unlock]; 136 | [connection performSelector:@selector(start) withObject:nil afterDelay:0.01]; 137 | [connection release]; 138 | 139 | return connection; 140 | } 141 | } 142 | 143 | #if __EGOIL_USE_NOTIF 144 | - (void)loadImageForURL:(NSURL*)aURL observer:(id)observer { 145 | if(!aURL) return; 146 | 147 | if([observer respondsToSelector:@selector(imageLoaderDidLoad:)]) { 148 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(imageLoaderDidLoad:) name:kImageNotificationLoaded(aURL) object:self]; 149 | } 150 | 151 | if([observer respondsToSelector:@selector(imageLoaderDidFailToLoad:)]) { 152 | [[NSNotificationCenter defaultCenter] addObserver:observer selector:@selector(imageLoaderDidFailToLoad:) name:kImageNotificationLoadFailed(aURL) object:self]; 153 | } 154 | 155 | [self loadImageForURL:aURL]; 156 | } 157 | 158 | - (UIImage*)imageForURL:(NSURL*)aURL shouldLoadWithObserver:(id)observer { 159 | if(!aURL) return nil; 160 | 161 | UIImage* anImage = [[EGOCache currentCache] imageForKey:keyForURL(aURL,nil)]; 162 | 163 | if(anImage) { 164 | return anImage; 165 | } else { 166 | [self loadImageForURL:aURL observer:observer]; 167 | return nil; 168 | } 169 | } 170 | 171 | - (void)removeObserver:(id)observer { 172 | [[NSNotificationCenter defaultCenter] removeObserver:observer name:nil object:self]; 173 | } 174 | 175 | - (void)removeObserver:(id)observer forURL:(NSURL*)aURL { 176 | [[NSNotificationCenter defaultCenter] removeObserver:observer name:kImageNotificationLoaded(aURL) object:self]; 177 | [[NSNotificationCenter defaultCenter] removeObserver:observer name:kImageNotificationLoadFailed(aURL) object:self]; 178 | } 179 | 180 | #endif 181 | 182 | #if __EGOIL_USE_BLOCKS 183 | - (void)loadImageForURL:(NSURL*)aURL completion:(void (^)(UIImage* image, NSURL* imageURL, NSError* error))completion { 184 | [self loadImageForURL:aURL style:nil styler:nil completion:completion]; 185 | } 186 | 187 | - (void)loadImageForURL:(NSURL*)aURL style:(NSString*)style styler:(UIImage* (^)(UIImage* image))styler completion:(void (^)(UIImage* image, NSURL* imageURL, NSError* error))completion { 188 | UIImage* anImage = [[EGOCache currentCache] imageForKey:keyForURL(aURL,style)]; 189 | 190 | if(anImage) { 191 | completion(anImage, aURL, nil); 192 | } else if(!anImage && styler && style && (anImage = [[EGOCache currentCache] imageForKey:keyForURL(aURL,nil)])) { 193 | dispatch_async(kStylerQueue, ^{ 194 | UIImage* image = styler(anImage); 195 | [[EGOCache currentCache] setImage:image forKey:keyForURL(aURL, style) withTimeoutInterval:604800]; 196 | dispatch_async(kCompletionsQueue, ^{ 197 | completion(image, aURL, nil); 198 | }); 199 | }); 200 | } else { 201 | EGOImageLoadConnection* connection = [self loadImageForURL:aURL]; 202 | void (^completionCopy)(UIImage* image, NSURL* imageURL, NSError* error) = [completion copy]; 203 | 204 | NSString* handlerKey = style ? style : kNoStyle; 205 | NSMutableDictionary* handler = [connection.handlers objectForKey:handlerKey]; 206 | 207 | if(!handler) { 208 | handler = [[NSMutableDictionary alloc] initWithCapacity:2]; 209 | [connection.handlers setObject:handler forKey:handlerKey]; 210 | 211 | [handler setObject:[NSMutableArray arrayWithCapacity:1] forKey:kCompletionsKey]; 212 | if(styler) { 213 | UIImage* (^stylerCopy)(UIImage* image) = [styler copy]; 214 | [handler setObject:stylerCopy forKey:kStylerKey]; 215 | [stylerCopy release]; 216 | } 217 | 218 | [handler release]; 219 | } 220 | 221 | [[handler objectForKey:kCompletionsKey] addObject:completionCopy]; 222 | [completionCopy release]; 223 | } 224 | } 225 | #endif 226 | 227 | - (BOOL)hasLoadedImageURL:(NSURL*)aURL { 228 | return [[EGOCache currentCache] hasCacheForKey:keyForURL(aURL,nil)]; 229 | } 230 | 231 | #pragma mark - 232 | #pragma mark URL Connection delegate methods 233 | 234 | - (void)imageLoadConnectionDidFinishLoading:(EGOImageLoadConnection *)connection { 235 | UIImage* anImage = [UIImage imageWithData:connection.responseData]; 236 | 237 | if(!anImage) { 238 | NSError* error = [NSError errorWithDomain:[connection.imageURL host] code:406 userInfo:nil]; 239 | 240 | #if __EGOIL_USE_NOTIF 241 | NSNotification* notification = [NSNotification notificationWithName:kImageNotificationLoadFailed(connection.imageURL) 242 | object:self 243 | userInfo:[NSDictionary dictionaryWithObjectsAndKeys:error,@"error",connection.imageURL,@"imageURL",nil]]; 244 | 245 | [[NSNotificationCenter defaultCenter] performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:YES]; 246 | #endif 247 | 248 | #if __EGOIL_USE_BLOCKS 249 | [self handleCompletionsForConnection:connection image:nil error:error]; 250 | #endif 251 | } else { 252 | [[EGOCache currentCache] setData:connection.responseData forKey:keyForURL(connection.imageURL,nil) withTimeoutInterval:604800]; 253 | 254 | [currentConnections removeObjectForKey:connection.imageURL]; 255 | self.currentConnections = [[currentConnections copy] autorelease]; 256 | 257 | #if __EGOIL_USE_NOTIF 258 | NSNotification* notification = [NSNotification notificationWithName:kImageNotificationLoaded(connection.imageURL) 259 | object:self 260 | userInfo:[NSDictionary dictionaryWithObjectsAndKeys:anImage,@"image",connection.imageURL,@"imageURL",nil]]; 261 | 262 | [[NSNotificationCenter defaultCenter] performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:YES]; 263 | #endif 264 | 265 | #if __EGOIL_USE_BLOCKS 266 | [self handleCompletionsForConnection:connection image:anImage error:nil]; 267 | #endif 268 | } 269 | 270 | 271 | 272 | [self cleanUpConnection:connection]; 273 | } 274 | 275 | - (void)imageLoadConnection:(EGOImageLoadConnection *)connection didFailWithError:(NSError *)error { 276 | [currentConnections removeObjectForKey:connection.imageURL]; 277 | self.currentConnections = [[currentConnections copy] autorelease]; 278 | 279 | #if __EGOIL_USE_NOTIF 280 | NSNotification* notification = [NSNotification notificationWithName:kImageNotificationLoadFailed(connection.imageURL) 281 | object:self 282 | userInfo:[NSDictionary dictionaryWithObjectsAndKeys:error,@"error",connection.imageURL,@"imageURL",nil]]; 283 | 284 | [[NSNotificationCenter defaultCenter] performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:YES]; 285 | #endif 286 | 287 | #if __EGOIL_USE_BLOCKS 288 | [self handleCompletionsForConnection:connection image:nil error:error]; 289 | #endif 290 | 291 | [self cleanUpConnection:connection]; 292 | } 293 | 294 | #if __EGOIL_USE_BLOCKS 295 | - (void)handleCompletionsForConnection:(EGOImageLoadConnection*)connection image:(UIImage*)image error:(NSError*)error { 296 | if([connection.handlers count] == 0) return; 297 | 298 | NSURL* imageURL = connection.imageURL; 299 | 300 | void (^callCompletions)(UIImage* anImage, NSArray* completions) = ^(UIImage* anImage, NSArray* completions) { 301 | dispatch_async(kCompletionsQueue, ^{ 302 | for(void (^completion)(UIImage* image, NSURL* imageURL, NSError* error) in completions) { 303 | completion(anImage, connection.imageURL, error); 304 | } 305 | }); 306 | }; 307 | 308 | for(NSString* styleKey in connection.handlers) { 309 | NSDictionary* handler = [connection.handlers objectForKey:styleKey]; 310 | UIImage* (^styler)(UIImage* image) = [handler objectForKey:kStylerKey]; 311 | if(!error && image && styler) { 312 | dispatch_async(kStylerQueue, ^{ 313 | UIImage* anImage = styler(image); 314 | [[EGOCache currentCache] setImage:anImage forKey:keyForURL(imageURL, styleKey) withTimeoutInterval:604800]; 315 | callCompletions(anImage, [handler objectForKey:kCompletionsKey]); 316 | }); 317 | } else { 318 | callCompletions(image, [handler objectForKey:kCompletionsKey]); 319 | } 320 | } 321 | } 322 | #endif 323 | 324 | #pragma mark - 325 | 326 | - (void)dealloc { 327 | #if __EGOIL_USE_BLOCKS 328 | dispatch_release(_operationQueue), _operationQueue = nil; 329 | #endif 330 | 331 | self.currentConnections = nil; 332 | [currentConnections release], currentConnections = nil; 333 | [connectionsLock release], connectionsLock = nil; 334 | [super dealloc]; 335 | } 336 | 337 | @end -------------------------------------------------------------------------------- /EGOImageView/EGOImageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // EGOImageView.h 3 | // EGOImageLoading 4 | // 5 | // Created by Shaun Harrison on 9/15/09. 6 | // Copyright (c) 2009-2010 enormego 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | #import 28 | #import "EGOImageLoader.h" 29 | 30 | @protocol EGOImageViewDelegate; 31 | @interface EGOImageView : UIImageView { 32 | @private 33 | NSURL* imageURL; 34 | UIImage* placeholderImage; 35 | id delegate; 36 | } 37 | 38 | - (id)initWithPlaceholderImage:(UIImage*)anImage; // delegate:nil 39 | - (id)initWithPlaceholderImage:(UIImage*)anImage delegate:(id)aDelegate; 40 | 41 | - (void)cancelImageLoad; 42 | 43 | @property(nonatomic,retain) NSURL* imageURL; 44 | @property(nonatomic,retain) UIImage* placeholderImage; 45 | @property(nonatomic,assign) id delegate; 46 | @end 47 | 48 | @protocol EGOImageViewDelegate 49 | @optional 50 | - (void)imageViewLoadedImage:(EGOImageView*)imageView; 51 | - (void)imageViewFailedToLoadImage:(EGOImageView*)imageView error:(NSError*)error; 52 | @end -------------------------------------------------------------------------------- /EGOImageView/EGOImageView.m: -------------------------------------------------------------------------------- 1 | // 2 | // EGOImageView.m 3 | // EGOImageLoading 4 | // 5 | // Created by Shaun Harrison on 9/15/09. 6 | // Copyright (c) 2009-2010 enormego 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | #import "EGOImageView.h" 28 | #import "EGOImageLoader.h" 29 | 30 | @implementation EGOImageView 31 | @synthesize imageURL, placeholderImage, delegate; 32 | 33 | - (id)initWithPlaceholderImage:(UIImage*)anImage { 34 | return [self initWithPlaceholderImage:anImage delegate:nil]; 35 | } 36 | 37 | - (id)initWithPlaceholderImage:(UIImage*)anImage delegate:(id)aDelegate { 38 | if((self = [super initWithImage:anImage])) { 39 | self.placeholderImage = anImage; 40 | self.delegate = aDelegate; 41 | } 42 | 43 | return self; 44 | } 45 | 46 | - (void)setImageURL:(NSURL *)aURL { 47 | if(imageURL) { 48 | [[EGOImageLoader sharedImageLoader] removeObserver:self forURL:imageURL]; 49 | [imageURL release]; 50 | imageURL = nil; 51 | } 52 | 53 | if(!aURL) { 54 | self.image = self.placeholderImage; 55 | imageURL = nil; 56 | return; 57 | } else { 58 | imageURL = [aURL retain]; 59 | } 60 | 61 | [[EGOImageLoader sharedImageLoader] removeObserver:self]; 62 | UIImage* anImage = [[EGOImageLoader sharedImageLoader] imageForURL:aURL shouldLoadWithObserver:self]; 63 | 64 | if(anImage) { 65 | self.image = anImage; 66 | 67 | // trigger the delegate callback if the image was found in the cache 68 | if([self.delegate respondsToSelector:@selector(imageViewLoadedImage:)]) { 69 | [self.delegate imageViewLoadedImage:self]; 70 | } 71 | } else { 72 | self.image = self.placeholderImage; 73 | } 74 | } 75 | 76 | #pragma mark - 77 | #pragma mark Image loading 78 | 79 | - (void)cancelImageLoad { 80 | [[EGOImageLoader sharedImageLoader] cancelLoadForURL:self.imageURL]; 81 | [[EGOImageLoader sharedImageLoader] removeObserver:self forURL:self.imageURL]; 82 | } 83 | 84 | - (void)imageLoaderDidLoad:(NSNotification*)notification { 85 | if(![[[notification userInfo] objectForKey:@"imageURL"] isEqual:self.imageURL]) return; 86 | 87 | UIImage* anImage = [[notification userInfo] objectForKey:@"image"]; 88 | self.image = anImage; 89 | [self setNeedsDisplay]; 90 | 91 | if([self.delegate respondsToSelector:@selector(imageViewLoadedImage:)]) { 92 | [self.delegate imageViewLoadedImage:self]; 93 | } 94 | } 95 | 96 | - (void)imageLoaderDidFailToLoad:(NSNotification*)notification { 97 | if(![[[notification userInfo] objectForKey:@"imageURL"] isEqual:self.imageURL]) return; 98 | 99 | if([self.delegate respondsToSelector:@selector(imageViewFailedToLoadImage:error:)]) { 100 | [self.delegate imageViewFailedToLoadImage:self error:[[notification userInfo] objectForKey:@"error"]]; 101 | } 102 | } 103 | 104 | #pragma mark - 105 | - (void)dealloc { 106 | [[EGOImageLoader sharedImageLoader] removeObserver:self]; 107 | self.delegate = nil; 108 | self.imageURL = nil; 109 | self.placeholderImage = nil; 110 | [super dealloc]; 111 | } 112 | 113 | @end 114 | --------------------------------------------------------------------------------