Skip to content
Browse files

Optimizing and offloading workload to secondary thread to free up the…

… main thread in TKImageCache.
  • Loading branch information...
1 parent cf5090a commit fd921f7fd6c8f4dd5d5c6e4b3c82522f4acab5fd Devin Ross committed Jun 29, 2012
View
BIN ...roj/project.xcworkspace/xcuserdata/devinross14.xcuserdatad/UserInterfaceState.xcuserstate
Binary file not shown.
View
15 src/TapkuLibrary/TKImageCache.h
@@ -30,7 +30,8 @@
*/
#import <Foundation/Foundation.h>
-#import <TapkuLibrary/TapkuLibrary.h>
+
+@class TKNetworkQueue,TKHTTPRequest;
/** An `TKImageCache` object provides a way to manage images between the network, disk and `NSCache`. */
@interface TKImageCache : NSCache {
@@ -60,6 +61,10 @@
/// @name Properties
///-------------------------
+/** Shows network activity monitor in status bar when network requests are created. */
+@property BOOL shouldNetworkActivity;
+
+
/** The queue that manages all network requests for images */
@property (strong,nonatomic) TKNetworkQueue *imagesQueue;
@@ -104,7 +109,7 @@
/** Checks to see if an image exists in cache or on disk for the given key.
@param key The key corresponding to a specific image.
- @return Returns YES is the image corresponding to the key exists on disk or in NSCache, otherwise NO.
+ @return Returns YES is the image corresponding to the key exists on disk or in NSCache, otherwise NO.
*/
- (BOOL) imageExistsWithKey:(NSString *)key;
@@ -120,11 +125,11 @@
/** Clears local cache and remove all images from disk */
- (void) clearCachedImages;
-/** Remove all images from disk that we're create earlier than a certain time
+/** Remove all images from disk that we're create earlier than a certain time
@param time The time for which all images files must be created before to remain on disk.
*/
- (void) removeCachedImagesFromDiskOlderThanTime:(NSTimeInterval)time;
-
+
///-------------------------
/// @name For subclassing
@@ -135,7 +140,7 @@
- (NSString *) cacheDirectoryPath; // for subclassing
-/** Perform image adjustments before storing it in local cache.
+/** Perform image adjustments before storing it in local cache.
@param image The image received from disk or the network.
@return The adjusted image.
View
185 src/TapkuLibrary/TKImageCache.m
@@ -30,13 +30,14 @@
*/
#import "TKImageCache.h"
-#import <TapkuLibrary/TapkuLibrary.h>
+#import "TKNetworkQueue.h"
+#import "TKHTTPRequest.h"
#pragma mark -
-@interface TKImageRequest : TKHTTPRequest
+@interface TKImageRequest : TKHTTPRequest
@property (strong,nonatomic) NSString *key;
-@end
+@end
@implementation TKImageRequest
@synthesize key;
@@ -60,6 +61,7 @@ @implementation TKImageCache
@synthesize cacheDirectoryName=_cacheDirectoryName,notificationName=_notificationName;
@synthesize timeTillRefreshCache=_timeTillRefreshCache;
@synthesize imagesQueue=_imagesQueue;
+@synthesize shouldNetworkActivity;
- (id) init{
self = [self initWithCacheDirectoryName:@"imagecache"];
@@ -73,6 +75,9 @@ - (id) initWithCacheDirectoryName:(NSString*)dirName{
_requestKeys = [[NSMutableDictionary alloc] init];
_imagesQueue = [[TKNetworkQueue alloc] init];
+
+ self.shouldNetworkActivity = YES;
+
cache_queue = dispatch_queue_create("com.tapku",NULL);
self.notificationName = @"NewCachedImageFile";
@@ -81,7 +86,7 @@ - (id) initWithCacheDirectoryName:(NSString*)dirName{
return self;
}
- (void) dealloc{
- dispatch_release(cache_queue);
+ dispatch_release(cache_queue);
}
@@ -90,107 +95,105 @@ - (UIImage*) imageForKey:(NSString*)key url:(NSURL*)url queueIfNeeded:(BOOL)queu
return [self imageForKey:key url:url queueIfNeeded:queueIfNeeded tag:0];
}
- (UIImage*) imageForKey:(NSString*)key url:(NSURL*)url queueIfNeeded:(BOOL)queueIfNeeded tag:(NSUInteger)tag{
-
+
if(key==nil) return nil;
- if([self objectForKey:key]) return [self objectForKey:key];
+
+ id obj = [self objectForKey:key];
+ if(obj) return obj;
if([self _imageExistsOnDiskWithKey:key]){
[self _readImageFromDiskWithKey:key tag:tag];
if(self.timeTillRefreshCache > 0){
+
+
NSString *path = [[self cacheDirectoryPath] stringByAppendingPathComponent:key];
NSDate *created = [[[NSFileManager defaultManager] attributesOfItemAtPath:path error:NULL] fileCreationDate];
NSTimeInterval timeSince = fabs([created timeIntervalSinceNow]);
if(_timeTillRefreshCache > timeSince) queueIfNeeded = NO;
-
+
}else
queueIfNeeded = NO;
}
-
- if(queueIfNeeded && url) [self _sendRequestForURL:url key:key tag:tag];
-
+
+ if(queueIfNeeded && url)
+ [self _sendRequestForURL:url key:key tag:tag];
+
return nil;
}
- (void) _sendRequestForURL:(NSURL*)url key:(NSString*)key tag:(NSUInteger)tag{
- if(key == nil || [_requestKeys objectForKey:key]!=nil) return;
-
-
- [_requestKeys setObject:[NSNull null] forKey:key];
- NSString *filePath = [self _filePathWithKey:key];
-
- TKImageRequest * request = (TKImageRequest*)[TKImageRequest requestWithURL:url];
- request.tag = tag;
- request.key = key;
- request.delegate = self;
- request.didFinishSelector = @selector(_requestDidFinish:);
- request.didFailSelector = @selector(_requestDidFail:);
- request.downloadDestinationPath = filePath;
- [_imagesQueue addOperation:request];
-
-
+ dispatch_async(cache_queue,^{
+
+ if([_requestKeys objectForKey:key]!=nil) return;
+
+ [_requestKeys setObject:[NSNull null] forKey:key];
+ NSString *filePath = [self _filePathWithKey:key];
+
+
+ TKImageRequest * request = (TKImageRequest*)[TKImageRequest requestWithURL:url];
+ request.tag = tag;
+ request.key = key;
+ request.delegate = self;
+ request.didFinishSelector = @selector(_requestDidFinish:);
+ request.didFailSelector = @selector(_requestDidFail:);
+ request.downloadDestinationPath = filePath;
+ request.showNetworkActivity = self.shouldNetworkActivity;
+ [_imagesQueue addOperation:request];
+
+ });
}
- (void) _requestDidFinish:(TKImageRequest*)request{
NSString *key = request.key;
- dispatch_async(dispatch_get_main_queue(), ^{
- if([_requestKeys objectForKey:key])
- [_requestKeys removeObjectForKey:key];
- });
+
if(request.statusCode != 200){
- [[NSFileManager defaultManager] removeItemAtPath:request.downloadDestinationPath error:nil];
+ dispatch_async(cache_queue,^{
+
+ if([_requestKeys objectForKey:key])
+ [_requestKeys removeObjectForKey:key];
+
+ [[NSFileManager defaultManager] removeItemAtPath:request.downloadDestinationPath error:nil];
+ });
return;
}
-
-
-
- if([[NSFileManager defaultManager] fileExistsAtPath:[self _filePathWithKey:key]]){
+ dispatch_async(cache_queue,^{
- dispatch_async(cache_queue,^{
- UIImage *cacheImage = [self adjustImageRecieved:[self _imageFromDiskWithKey:key]];
-
-
- if(cacheImage){
-
-
- NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:request.key,@"key",cacheImage,@"image",[NSNumber numberWithUnsignedInt:request.tag],@"tag",nil];
-
-
- dispatch_async(dispatch_get_main_queue(), ^{
-
- if(_diskKeys) [_diskKeys setObject:[NSNull null] forKey:request.key];
-
-
- [self setObject:cacheImage forKey:request.key];
- //[[NSNotificationCenter defaultCenter] postNotificationName:self.notificationName object:dict];
-
- [[NSNotificationCenter defaultCenter] postNotificationName:self.notificationName object:self userInfo:dict];
-
-
- });
- }
- });
+ if([_requestKeys objectForKey:key])
+ [_requestKeys removeObjectForKey:key];
- }
+ UIImage *cacheImage = [self adjustImageRecieved:[self _imageFromDiskWithKey:key]];
+ if(cacheImage==nil) return;
+
+ [self setObject:cacheImage forKey:request.key];
+ NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:key,@"key",cacheImage,@"image",[NSNumber numberWithUnsignedInt:request.tag],@"tag",nil];
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [_diskKeys setObject:[NSNull null] forKey:request.key];
+ [[NSNotificationCenter defaultCenter] postNotificationName:self.notificationName object:self userInfo:dict];
+ });
+
+ });
}
- (void) _requestDidFail:(TKImageRequest*)request{
- NSString *key = request.key;
-
- dispatch_async(dispatch_get_main_queue(), ^{
+
+ dispatch_async(cache_queue,^{
+ NSString *key = request.key;
+
if([_requestKeys objectForKey:key])
[_requestKeys removeObjectForKey:key];
});
@@ -209,7 +212,10 @@ - (UIImage*) adjustImageRecieved:(UIImage*)image{
- (void) cancelOperations{
[_imagesQueue cancelAllOperations];
- [_requestKeys removeAllObjects];
+ dispatch_async(cache_queue,^{
+
+ [_requestKeys removeAllObjects];
+ });
}
- (void) clearCachedImages{
@@ -226,20 +232,17 @@ - (void) clearCachedImages{
NSString *path = [[self cacheDirectoryPath] stringByAppendingPathComponent:file];
[[NSFileManager defaultManager] removeItemAtPath:path error:&error];
- }
+ }
}
});
-
+
}
- (void) removeCachedImagesFromDiskOlderThanTime:(NSTimeInterval)time{
-
UIBackgroundTaskIdentifier bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
-
-
NSError* error = nil;
NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self cacheDirectoryPath] error:&error];
@@ -250,31 +253,23 @@ - (void) removeCachedImagesFromDiskOlderThanTime:(NSTimeInterval)time{
NSDate *created = [[[NSFileManager defaultManager] attributesOfItemAtPath:path error:NULL] fileCreationDate];
NSTimeInterval timeSince = fabs([created timeIntervalSinceNow]);
-
-
-
if(timeSince > time){
-
if(_diskKeys) [_diskKeys removeObjectForKey:file];
-
[[NSFileManager defaultManager] removeItemAtPath:[[self cacheDirectoryPath] stringByAppendingPathComponent:file] error:&error];
}
-
- }
+ }
}
-
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
-
}
- (void) printAllCaching{
NSError* error = nil;
NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self cacheDirectoryPath] error:&error];
- NSLog(@"%@",files);
-
+ TKLog(@"%@",files);
+
}
@@ -288,8 +283,11 @@ - (NSString *) _filePathWithKey:(NSString *)key{
}
- (BOOL) _imageExistsOnDiskWithKey:(NSString *)key{
+
if(_diskKeys) return [_diskKeys objectForKey:key]==nil ? NO : YES;
+
+
return [[NSFileManager defaultManager] fileExistsAtPath:[self _filePathWithKey:key]];
}
- (UIImage*) _imageFromDiskWithKey:(NSString*)key{
@@ -300,21 +298,20 @@ - (void) _readImageFromDiskWithKey:(NSString*)key tag:(NSUInteger)tag{
dispatch_async(cache_queue,^{
+
UIImage *cacheImage = [self adjustImageRecieved:[self _imageFromDiskWithKey:key]];
- if(cacheImage!=nil){
-
- dispatch_async(dispatch_get_main_queue(), ^{
- [self setObject:cacheImage forKey:key];
- NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:key,@"key",cacheImage,@"image",[NSNumber numberWithUnsignedInt:tag],@"tag",nil];
- //[[NSNotificationCenter defaultCenter] postNotificationName:self.notificationName object:dict];
-
- [[NSNotificationCenter defaultCenter] postNotificationName:self.notificationName object:self userInfo:dict];
-
- });
- usleep(10000);
-
-
- }
+
+ if(cacheImage==nil) return;
+ [self setObject:cacheImage forKey:key];
+ NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:key,@"key",cacheImage,@"image",[NSNumber numberWithUnsignedInt:tag],@"tag",nil];
+
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [[NSNotificationCenter defaultCenter] postNotificationName:self.notificationName object:self userInfo:dict];
+ });
+
+
+
});
}

0 comments on commit fd921f7

Please sign in to comment.
Something went wrong with that request. Please try again.