Skip to content

Commit 0e037d0

Browse files
author
hzlujunfeng
committed
SD增加缓存图片到离线目录
1 parent ab56489 commit 0e037d0

File tree

8 files changed

+346
-5
lines changed

8 files changed

+346
-5
lines changed

SDWebImage/SDImageCache.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ typedef enum SDImageCacheType SDImageCacheType;
7777
*/
7878
- (void)storeImage:(UIImage *)image forKey:(NSString *)key;
7979

80+
/**
81+
* <NTES DIY SDWebImage>
82+
* Store the image to an eternal folder unless user want to clean it.
83+
* Used for offline image in download manager
84+
*/
85+
- (void)storeImage:(UIImage *)image forKey:(NSString *)key isEternal:(BOOL)isEternal;
86+
8087
/**
8188
* Store an image into memory and optionally disk cache at the given key.
8289
*
@@ -99,6 +106,11 @@ typedef enum SDImageCacheType SDImageCacheType;
99106
*/
100107
- (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk;
101108

109+
/**
110+
* <NTES DIY SDWebImage>
111+
*/
112+
- (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk isEternal:(BOOL)isEternal;
113+
102114
/**
103115
* Query the disk cache asynchronously.
104116
*
@@ -127,6 +139,12 @@ typedef enum SDImageCacheType SDImageCacheType;
127139
*/
128140
- (void)removeImageForKey:(NSString *)key;
129141

142+
/**
143+
* <NTES DIY SDWebImage>
144+
* 删除离线目录里的图片(非缓存目录)
145+
*/
146+
- (void)removeImageFromEternalDisk:(NSString*)key;
147+
130148
/**
131149
* Remove the image from memory and optionaly disk cache synchronously
132150
*
@@ -170,4 +188,8 @@ typedef enum SDImageCacheType SDImageCacheType;
170188
*/
171189
- (BOOL)diskImageExistsWithKey:(NSString *)key;
172190

191+
//<NTES DIY SDWebImage> make interface public
192+
- (NSString *)defaultCachePathForKey:(NSString *)key;
193+
- (NSString *)eternalCachePathForKey:(NSString *)key;
194+
173195
@end

SDWebImage/SDImageCache.m

Lines changed: 138 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313
#import <mach/mach.h>
1414
#import <mach/mach_host.h>
1515

16+
//<NTES DIY SDWebImage>
17+
#ifndef kAppRootDirectory
18+
#define kAppRootDirectory @"UserData" //set up for application data root dir
19+
#endif
20+
#define NEW_ETERNAL_CACHE_DIR_NAME @"ImageStorage"
21+
1622
static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week
1723
// PNG signature bytes and data (below)
1824
static unsigned char kPNGSignatureBytes[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
@@ -40,6 +46,9 @@ @interface SDImageCache ()
4046
@property (strong, nonatomic) NSMutableArray *customPaths;
4147
@property (SDDispatchQueueSetterSementics, nonatomic) dispatch_queue_t ioQueue;
4248

49+
//<NTES DIY SDWebImage>
50+
@property (strong, nonatomic) NSString *eternalDiskCachePath;
51+
4352
@end
4453

4554

@@ -82,9 +91,15 @@ - (id)initWithNamespace:(NSString *)ns
8291
_memCache.name = fullNamespace;
8392

8493
// Init the disk cache
85-
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
86-
_diskCachePath = [paths[0] stringByAppendingPathComponent:fullNamespace];
87-
94+
// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
95+
// _diskCachePath = [paths[0] stringByAppendingPathComponent:fullNamespace];
96+
97+
//<NTES DIY SDWebImage> init the disk cache
98+
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
99+
NSString *rootDir = [paths[0] stringByAppendingPathComponent:kAppRootDirectory];
100+
_diskCachePath = [rootDir stringByAppendingPathComponent:fullNamespace];
101+
_eternalDiskCachePath = [rootDir stringByAppendingPathComponent:NEW_ETERNAL_CACHE_DIR_NAME];
102+
88103
dispatch_sync(_ioQueue, ^
89104
{
90105
_fileManager = NSFileManager.new;
@@ -144,6 +159,12 @@ - (NSString *)defaultCachePathForKey:(NSString *)key
144159
return [self cachePathForKey:key inPath:self.diskCachePath];
145160
}
146161

162+
//<NTES DIY SDWebImage> 离线图片的文件路径
163+
- (NSString *)eternalCachePathForKey:(NSString *)key
164+
{
165+
return [self cachePathForKey:key inPath:self.eternalDiskCachePath];
166+
}
167+
147168
- (NSString *)cachedFileNameForKey:(NSString *)key
148169
{
149170
const char *str = [key UTF8String];
@@ -223,22 +244,108 @@ - (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate image
223244
}
224245
}
225246

247+
/**
248+
不改原始方法-->
249+
- (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk
250+
251+
*/
252+
//<NTES DIY SDWebImage>(新增方法)
253+
- (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk isEternal:(BOOL)isEternal
254+
{
255+
if(!isEternal)
256+
{
257+
[self storeImage:image recalculateFromImage:recalculate imageData:imageData forKey:key toDisk:toDisk];
258+
return;
259+
}
260+
261+
if (!image || !key)
262+
{
263+
return;
264+
}
265+
266+
[self.memCache setObject:image forKey:key cost:image.size.height * image.size.width * image.scale];
267+
268+
if (toDisk)
269+
{
270+
dispatch_async(self.ioQueue, ^
271+
{
272+
NSData *data = imageData;
273+
274+
if (image && (recalculate || !data))
275+
{
276+
#if TARGET_OS_IPHONE
277+
// We need to determine if the image is a PNG or a JPEG
278+
// PNGs are easier to detect because they have a unique signature (http://www.w3.org/TR/PNG-Structure.html)
279+
// The first eight bytes of a PNG file always contain the following (decimal) values:
280+
// 137 80 78 71 13 10 26 10
281+
282+
// We assume the image is PNG, in case the imageData is nil (i.e. if trying to save a UIImage directly),
283+
// we will consider it PNG to avoid loosing the transparency
284+
BOOL imageIsPng = YES;
285+
286+
// But if we have an image data, we will look at the preffix
287+
if ([imageData length] >= [kPNGSignatureData length])
288+
{
289+
imageIsPng = ImageDataHasPNGPreffix(imageData);
290+
}
291+
292+
if (imageIsPng)
293+
{
294+
data = UIImagePNGRepresentation(image);
295+
}
296+
else
297+
{
298+
data = UIImageJPEGRepresentation(image, (CGFloat)1.0);
299+
}
300+
#else
301+
data = [NSBitmapImageRep representationOfImageRepsInArray:image.representations usingType: NSJPEGFileType properties:nil];
302+
#endif
303+
}
304+
305+
if (data)
306+
{
307+
// Can't use defaultManager another thread
308+
NSFileManager *fileManager = NSFileManager.new;
309+
310+
if (![fileManager fileExistsAtPath:_eternalDiskCachePath]) //离线目录
311+
{
312+
[fileManager createDirectoryAtPath:_eternalDiskCachePath withIntermediateDirectories:YES attributes:nil error:NULL];
313+
}
314+
315+
[fileManager createFileAtPath:[self eternalCachePathForKey:key] contents:data attributes:nil];
316+
}
317+
});
318+
}
319+
}
320+
226321
- (void)storeImage:(UIImage *)image forKey:(NSString *)key
227322
{
228323
[self storeImage:image recalculateFromImage:YES imageData:nil forKey:key toDisk:YES];
229324
}
230325

326+
//<NTES DIY SDWebImage>(新增方法)
327+
- (void)storeImage:(UIImage *)image forKey:(NSString *)key isEternal:(BOOL)isEternal
328+
{
329+
[self storeImage:image recalculateFromImage:YES imageData:nil forKey:key toDisk:YES isEternal:isEternal];
330+
}
331+
231332
- (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk
232333
{
233334
[self storeImage:image recalculateFromImage:YES imageData:nil forKey:key toDisk:toDisk];
234335
}
235336

337+
//<NTES DIY SDWebImage>(改动原始方法)
236338
- (BOOL)diskImageExistsWithKey:(NSString *)key
237339
{
238340
__block BOOL exists = NO;
239341
dispatch_sync(_ioQueue, ^
240342
{
241343
exists = [_fileManager fileExistsAtPath:[self defaultCachePathForKey:key]];
344+
//<NTES DIY SDWebImage>默认路径找不到,去离线目录找一次
345+
if(!exists)
346+
{
347+
exists = [_fileManager fileExistsAtPath:[self eternalCachePathForKey:key]];
348+
}
242349
});
243350

244351
return exists;
@@ -269,6 +376,7 @@ - (UIImage *)imageFromDiskCacheForKey:(NSString *)key
269376
return diskImage;
270377
}
271378

379+
//<NTES DIY SDWebImage>(改动原始方法)
272380
- (NSData *)diskImageDataBySearchingAllPathsForKey:(NSString *)key
273381
{
274382
NSString *defaultPath = [self defaultCachePathForKey:key];
@@ -277,6 +385,14 @@ - (NSData *)diskImageDataBySearchingAllPathsForKey:(NSString *)key
277385
{
278386
return data;
279387
}
388+
389+
//<NTES DIY SDWebImage> 查找离线目录
390+
NSString *eternalPath = [self eternalCachePathForKey:key];
391+
NSData *eternalData = [NSData dataWithContentsOfFile:eternalPath];
392+
if (eternalData)
393+
{
394+
return eternalData;
395+
}
280396

281397
for (NSString *path in self.customPaths)
282398
{
@@ -380,6 +496,25 @@ - (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk
380496
}
381497
}
382498

499+
/**
500+
* 从离线目录删除图片
501+
*/
502+
//<NTES DIY SDWebImage>(新增方法)
503+
- (void)removeImageFromEternalDisk:(NSString*)key
504+
{
505+
if (key == nil)
506+
{
507+
return;
508+
}
509+
510+
[self.memCache removeObjectForKey:key];
511+
512+
dispatch_async(self.ioQueue, ^
513+
{
514+
[[NSFileManager defaultManager] removeItemAtPath:[self eternalCachePathForKey:key] error:nil];
515+
});
516+
}
517+
383518
- (void)setMaxMemoryCost:(NSUInteger)maxMemoryCost
384519
{
385520
self.memCache.totalCostLimit = maxMemoryCost;

SDWebImage/SDWebImageManager.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ SDWebImageManager *manager = [SDWebImageManager sharedManager];
177177
progress:(SDWebImageDownloaderProgressBlock)progressBlock
178178
completed:(SDWebImageCompletedWithFinishedBlock)completedBlock;
179179

180+
/** <NTES DIY SDWebImage>
181+
* 下载图片到离线目录
182+
*/
183+
- (id<SDWebImageOperation>)downloadWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedWithFinishedBlock)completedBlock isEternal:(BOOL)isEternal;
184+
185+
180186
/**
181187
* Cancel all current opreations
182188
*/

SDWebImage/SDWebImageManager.m

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,20 @@ - (BOOL)diskImageExistsForURL:(NSURL *)url
7272
return [self.imageCache diskImageExistsWithKey:key];
7373
}
7474

75+
76+
77+
/**
78+
* <NTES DIY SDWebImage> (改动原方法)
79+
*/
7580
- (id<SDWebImageOperation>)downloadWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedWithFinishedBlock)completedBlock
81+
{
82+
return [self downloadWithURL:url options:options progress:progressBlock completed:completedBlock isEternal:NO];
83+
}
84+
85+
/** <NTES DIY SDWebImage>
86+
* 下载图片到离线目录
87+
*/
88+
- (id<SDWebImageOperation>)downloadWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedWithFinishedBlock)completedBlock isEternal:(BOOL)isEternal
7689
{
7790
// Invoking this method without a completedBlock is pointless
7891
NSParameterAssert(completedBlock);
@@ -200,8 +213,9 @@ - (BOOL)diskImageExistsForURL:(NSURL *)url
200213

201214
if (transformedImage && finished)
202215
{
216+
//<NTES DIY SDWebImage>
203217
BOOL imageWasTransformed = ![transformedImage isEqual:downloadedImage];
204-
[self.imageCache storeImage:transformedImage recalculateFromImage:imageWasTransformed imageData:data forKey:key toDisk:cacheOnDisk];
218+
[self.imageCache storeImage:transformedImage recalculateFromImage:imageWasTransformed imageData:data forKey:key toDisk:cacheOnDisk isEternal:isEternal];
205219
}
206220
});
207221
}
@@ -214,7 +228,8 @@ - (BOOL)diskImageExistsForURL:(NSURL *)url
214228

215229
if (downloadedImage && finished)
216230
{
217-
[self.imageCache storeImage:downloadedImage recalculateFromImage:NO imageData:data forKey:key toDisk:cacheOnDisk];
231+
//<NTES DIY SDWebImage>
232+
[self.imageCache storeImage:downloadedImage recalculateFromImage:NO imageData:data forKey:key toDisk:cacheOnDisk isEternal:isEternal];
218233
}
219234
}
220235
}
@@ -231,6 +246,23 @@ - (BOOL)diskImageExistsForURL:(NSURL *)url
231246
}
232247
else if (image)
233248
{
249+
//<NTES DIY SDWebImage>
250+
//【缓存里已有的图片未保存到离线目录里的问题】可能1:离线图片时图片已在缓存与内存中;可能2:离线图片时图片仅在内存中但不在缓存中
251+
//【离线图片如果下载失败,增加恢复机制,需要外部支持,如播放页面加载下载歌曲图片时显示声明图片需要离线】
252+
if(isEternal)
253+
{
254+
NSString *cachePath = [self.imageCache defaultCachePathForKey:key];
255+
NSString *eternalPath = [self.imageCache eternalCachePathForKey:key];
256+
if(![[NSFileManager defaultManager] fileExistsAtPath:eternalPath] && ![[NSFileManager defaultManager] fileExistsAtPath:cachePath])
257+
{
258+
[self.imageCache storeImage:image forKey:key isEternal:YES];
259+
}
260+
else if(![[NSFileManager defaultManager] fileExistsAtPath:eternalPath] && [[NSFileManager defaultManager] fileExistsAtPath:cachePath])
261+
{
262+
[[NSFileManager defaultManager] moveItemAtPath:cachePath toPath:eternalPath error:nil];
263+
}
264+
}
265+
234266
dispatch_main_sync_safe(^
235267
{
236268
completedBlock(image, nil, cacheType, YES);

SDWebImage/UIButton+WebCache.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@
9393
*/
9494
- (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock;
9595

96+
/**
97+
* <NTES DIY SDWebImage>
98+
* UIButton增加离线保存图片
99+
*/
100+
- (void)setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock isEternal:(BOOL)isEternal;
101+
96102
/**
97103
* Set the backgroundImageView `image` with an `url`.
98104
*
@@ -171,6 +177,12 @@
171177
*/
172178
- (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock;
173179

180+
/**
181+
* <NTES DIY SDWebImage>
182+
* UIButton增加离线保存背景图片
183+
*/
184+
- (void)setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletedBlock)completedBlock isEternal:(BOOL)isEternal;
185+
174186
/**
175187
* Cancel the current download
176188
*/

0 commit comments

Comments
 (0)