diff --git a/Examples/CustomPathImages/4ad9ae8eabfec60b40bf48f0bfc2d120 b/Examples/CustomPathImages/4ad9ae8eabfec60b40bf48f0bfc2d120 new file mode 100644 index 00000000..f57c8e1b Binary files /dev/null and b/Examples/CustomPathImages/4ad9ae8eabfec60b40bf48f0bfc2d120 differ diff --git a/Examples/SDWebImage Demo.xcodeproj/project.pbxproj b/Examples/SDWebImage Demo.xcodeproj/project.pbxproj index 893e854e..682f88d5 100644 --- a/Examples/SDWebImage Demo.xcodeproj/project.pbxproj +++ b/Examples/SDWebImage Demo.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 3E75A9861742DBE700DA412D /* CustomPathImages in Resources */ = {isa = PBXBuildFile; fileRef = 3E75A9851742DBE700DA412D /* CustomPathImages */; }; 531041C1157EAC8F00BBABC3 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 537612E6155ABA44005750A4 /* ImageIO.framework */; }; 5376129A155AB74D005750A4 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53761299155AB74D005750A4 /* UIKit.framework */; }; 5376129C155AB74D005750A4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5376129B155AB74D005750A4 /* Foundation.framework */; }; @@ -48,6 +49,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 3E75A9851742DBE700DA412D /* CustomPathImages */ = {isa = PBXFileReference; lastKnownFileType = folder; path = CustomPathImages; sourceTree = SOURCE_ROOT; }; 53761295155AB74D005750A4 /* SDWebImage Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "SDWebImage Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 53761299155AB74D005750A4 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 5376129B155AB74D005750A4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; @@ -120,6 +122,7 @@ 5376129F155AB74D005750A4 /* SDWebImage Demo */ = { isa = PBXGroup; children = ( + 3E75A9851742DBE700DA412D /* CustomPathImages */, 537612A8155AB74D005750A4 /* AppDelegate.h */, 537612A9155AB74D005750A4 /* AppDelegate.m */, 537612AB155AB74D005750A4 /* MasterViewController.h */, @@ -235,6 +238,7 @@ 53A2B50D155B155A00B12423 /* placeholder.png in Resources */, 53A2B50E155B155A00B12423 /* placeholder@2x.png in Resources */, 53EEC18916484553007601E1 /* Default-568h@2x.png in Resources */, + 3E75A9861742DBE700DA412D /* CustomPathImages in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Examples/SDWebImage Demo/AppDelegate.m b/Examples/SDWebImage Demo/AppDelegate.m index 721d4ac3..3e5f51e0 100644 --- a/Examples/SDWebImage Demo/AppDelegate.m +++ b/Examples/SDWebImage Demo/AppDelegate.m @@ -10,6 +10,8 @@ #import "MasterViewController.h" +#import + @implementation AppDelegate @synthesize window = _window; @@ -17,6 +19,10 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + //Add a custom read-only cache path + NSString *bundledPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"CustomPathImages"]; + [[SDImageCache sharedImageCache] addReadOnlyCachePath:bundledPath]; + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. diff --git a/SDWebImage/SDImageCache.h b/SDWebImage/SDImageCache.h index 3055f3d2..d3699b60 100644 --- a/SDWebImage/SDImageCache.h +++ b/SDWebImage/SDImageCache.h @@ -56,6 +56,14 @@ typedef enum SDImageCacheType SDImageCacheType; */ - (id)initWithNamespace:(NSString *)ns; +/** + * Add a read-only cache path to search for images pre-cached by SDImageCache + * Useful if you want to bundle pre-loaded images with your app + * + * @param path The path to use for this read-only cache path + */ +- (void)addReadOnlyCachePath:(NSString *)path; + /** * Store an image into memory and disk cache at the given key. * diff --git a/SDWebImage/SDImageCache.m b/SDWebImage/SDImageCache.m index 5c7251ba..a926b11b 100644 --- a/SDWebImage/SDImageCache.m +++ b/SDWebImage/SDImageCache.m @@ -19,6 +19,7 @@ static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week @property (strong, nonatomic) NSCache *memCache; @property (strong, nonatomic) NSString *diskCachePath; +@property (strong, nonatomic) NSMutableArray *customPaths; @property (SDDispatchQueueSetterSementics, nonatomic) dispatch_queue_t ioQueue; @end @@ -82,9 +83,33 @@ static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week SDDispatchQueueRelease(_ioQueue); } +- (void)addReadOnlyCachePath:(NSString *)path +{ + if (!self.customPaths) + { + self.customPaths = NSMutableArray.new; + } + + if (![self.customPaths containsObject:path]) + { + [self.customPaths addObject:path]; + } +} + #pragma mark SDImageCache (private) -- (NSString *)cachePathForKey:(NSString *)key +- (NSString *)cachePathForKey:(NSString *)key inPath:(NSString *)path +{ + NSString *filename = [self cachedFileNameForKey:key]; + return [path stringByAppendingPathComponent:filename]; +} + +- (NSString *)defaultCachePathForKey:(NSString *)key +{ + return [self cachePathForKey:key inPath:self.diskCachePath]; +} + +- (NSString *)cachedFileNameForKey:(NSString *)key { const char *str = [key UTF8String]; unsigned char r[CC_MD5_DIGEST_LENGTH]; @@ -92,7 +117,7 @@ static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week NSString *filename = [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]]; - return [self.diskCachePath stringByAppendingPathComponent:filename]; + return filename; } #pragma mark ImageCache @@ -134,7 +159,7 @@ static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week [fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL]; } - [fileManager createFileAtPath:[self cachePathForKey:key] contents:data attributes:nil]; + [fileManager createFileAtPath:[self defaultCachePathForKey:key] contents:data attributes:nil]; } }); } @@ -175,10 +200,30 @@ static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week return diskImage; } +- (NSData *)diskImageDataBySearchingAllPathsForKey:(NSString *)key +{ + NSString *defaultPath = [self defaultCachePathForKey:key]; + NSData *data = [NSData dataWithContentsOfFile:defaultPath]; + if (data) + { + return data; + } + + for (NSString *path in self.customPaths) + { + NSString *filePath = [self cachePathForKey:key inPath:path]; + NSData *imageData = [NSData dataWithContentsOfFile:filePath]; + if (imageData) { + return imageData; + } + } + + return nil; +} + - (UIImage *)diskImageForKey:(NSString *)key { - NSString *path = [self cachePathForKey:key]; - NSData *data = [NSData dataWithContentsOfFile:path]; + NSData *data = [self diskImageDataBySearchingAllPathsForKey:key]; if (data) { if ([data sd_isGIF]) @@ -259,7 +304,7 @@ static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week { dispatch_async(self.ioQueue, ^ { - [[NSFileManager defaultManager] removeItemAtPath:[self cachePathForKey:key] error:nil]; + [[NSFileManager defaultManager] removeItemAtPath:[self defaultCachePathForKey:key] error:nil]; }); } }