Skip to content

Commit

Permalink
image cache added to NYXProgressiveImageView
Browse files Browse the repository at this point in the history
  • Loading branch information
Raphael Petegrosso committed Feb 7, 2012
1 parent 5df242f commit 37d261f
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 4 deletions.
7 changes: 7 additions & 0 deletions Classes/NYXProgressiveImageView.h
Expand Up @@ -20,9 +20,16 @@
#pragma mark - Public messages
/// Launch the image download
-(void)loadImageAtURL:(NSURL*)url;
// Caching
+ (void)resetImageCache; // This will remove all cached images managed by any NYXProgressiveImageView instances

#define NYX_DEFAULT_CACHE_TIME 604800 // 7 days

#pragma mark - Public properties
/// Delegate (use weak if you target only iOS 5)
@property (nonatomic, assign) IBOutlet id <NYXProgressiveImageViewDelegate> delegate;
// Caching
@property (nonatomic,getter = isCaching) BOOL caching;
@property (nonatomic) NSTimeInterval cacheTime;

@end
163 changes: 159 additions & 4 deletions Classes/NYXProgressiveImageView.m
Expand Up @@ -11,10 +11,15 @@
#import "NYXProgressiveImageView.h"
#import "NYXImagesHelper.h"
#import <ImageIO/ImageIO.h>

#import <CommonCrypto/CommonDigest.h>

@interface NYXProgressiveImageView()
-(CGImageRef)createTransitoryImage:(CGImageRef)partialImage CF_RETURNS_RETAINED;
- (CGImageRef)createTransitoryImage:(CGImageRef)partialImage CF_RETURNS_RETAINED;
- (void) initializeAttributes;
+ (NSString*)cacheDirectoryAddress;
- (NSString*)cachedImageSystemName;
- (void)resetCache;

@end


Expand All @@ -34,12 +39,85 @@ @implementation NYXProgressiveImageView
long long _expectedSize;
/// Connection queue
dispatch_queue_t _queue;
// Url
NSURL * _url;
}

@synthesize delegate = _delegate;
@synthesize caching = _caching;
@synthesize cacheTime = _cacheTime;

#pragma mark - Init
-(id)init {
self = [super init];
if (self) {
[self initializeAttributes];
}
return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self initializeAttributes];
}
return self;
}
-(id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self initializeAttributes];
}
return self;
}
-(id)initWithImage:(UIImage *)image {
self = [super initWithImage:image];
if (self) {
[self initializeAttributes];
}
return self;
}
-(id)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highlightedImage {
self = [super initWithImage:image highlightedImage:highlightedImage];
if (self) {
[self initializeAttributes];
}
return self;
}

#pragma mark - Public

-(void)loadImageAtURL:(NSURL*)url
{

_url = url;

if (_caching) {

NSFileManager *fileManager = [NSFileManager defaultManager];

// check if file exists on cache
if ([fileManager fileExistsAtPath:[[NYXProgressiveImageView cacheDirectoryAddress] stringByAppendingPathComponent:[self cachedImageSystemName]]])
{
NSDate *mofificationDate = [[fileManager attributesOfItemAtPath:[[NYXProgressiveImageView cacheDirectoryAddress] stringByAppendingPathComponent:[self cachedImageSystemName]] error:nil] objectForKey:NSFileModificationDate];

// check modification date
if (-[mofificationDate timeIntervalSinceNow] > self.cacheTime) {
// Removes old cache file...
[self resetCache];
} else {

// Loads image from cache without networking
NSData *localImageData = [NSData dataWithContentsOfFile:[[NYXProgressiveImageView cacheDirectoryAddress] stringByAppendingPathComponent:[self cachedImageSystemName]]];
UIImage *localImage = [UIImage imageWithData:localImageData];

self.image = localImage;

return;

}
}
}

_queue = dispatch_queue_create("com.cocoabyss.pdlqueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(_queue, ^{
NSURLRequest* request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:10.0f];
Expand All @@ -48,6 +126,12 @@ -(void)loadImageAtURL:(NSURL*)url
[_connection start];
CFRunLoopRun();
});

}

+ (void)resetImageCache
{
[[NSFileManager defaultManager] removeItemAtPath:[NYXProgressiveImageView cacheDirectoryAddress] error:nil];
}

#pragma mark - NSURLConnectionDelegate
Expand Down Expand Up @@ -123,10 +207,45 @@ -(void)connectionDidFinishLoading:(NSURLConnection*)connection
[_delegate imageDownloadCompletedWithImage:img];
_dataTemp = nil;
}


if (self.caching)
{
// Create cache directory if it doesn't exist
BOOL isDir = YES;

NSFileManager *fileManager = [NSFileManager defaultManager];

if (![fileManager fileExistsAtPath:[NYXProgressiveImageView cacheDirectoryAddress] isDirectory:&isDir]) {
[fileManager createDirectoryAtPath:[NYXProgressiveImageView cacheDirectoryAddress] withIntermediateDirectories:NO attributes:nil error:nil];
}

// Write image cache file
NSError *error;

NSData *cachedImage;

// Is it PNG or JPG/JPEG?
if([[_url absoluteString] rangeOfString: @".png" options: NSCaseInsensitiveSearch].location != NSNotFound)
{
cachedImage = UIImagePNGRepresentation(self.image);
}
else
{
cachedImage = UIImageJPEGRepresentation(self.image, 1.0);
}

@try {
[cachedImage writeToFile:[[NYXProgressiveImageView cacheDirectoryAddress] stringByAppendingPathComponent:[self cachedImageSystemName]] options:NSDataWritingAtomic error:&error];
}
@catch (NSException * e) {
// TODO: error handling
}
}

if (_imageSource)
CFRelease(_imageSource);
_connection = nil;
_url = nil;
dispatch_release(_queue);
CFRunLoopStop(CFRunLoopGetCurrent());
}
Expand All @@ -135,7 +254,7 @@ -(void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
{
if ([_delegate respondsToSelector:@selector(imageDownloadFailedWithData:)])
[_delegate imageDownloadFailedWithData:_dataTemp];

_dataTemp = nil;
if (_imageSource)
CFRelease(_imageSource);
Expand All @@ -157,4 +276,40 @@ -(CGImageRef)createTransitoryImage:(CGImageRef)partialImage
return goodImageRef;
}

-(void) initializeAttributes {
_cacheTime = (double)NYX_DEFAULT_CACHE_TIME;
_caching = NO;
}

// caching methods

+ (NSString*)cacheDirectoryAddress
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
return [documentsDirectoryPath stringByAppendingPathComponent:@"NYXProgressiveImageViewCache"];
}

- (void)resetCache
{
[[NSFileManager defaultManager] removeItemAtPath:[[NYXProgressiveImageView cacheDirectoryAddress] stringByAppendingPathComponent:[self cachedImageSystemName]] error:nil];
}

- (NSString*)cachedImageSystemName
{
const char *concat_str = [[_url absoluteString] UTF8String];
if (concat_str == nil)
{
return @"";
}

unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(concat_str, strlen(concat_str), result);
NSMutableString *hash = [NSMutableString string];
for (int i = 0; i < 16; i++) {
[hash appendFormat:@"%02X", result[i]];
}

return [hash lowercaseString];
}
@end

0 comments on commit 37d261f

Please sign in to comment.