Skip to content

Commit 3bf1000

Browse files
committed
Add bridge for YYCache to support SDImageCache protocol and custom image cache
1 parent f1c99f0 commit 3bf1000

File tree

3 files changed

+334
-2
lines changed

3 files changed

+334
-2
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* This file is part of the SDWebImage-YYCache package.
3+
*
4+
* For the full copyright and license information, please view the LICENSE
5+
* file that was distributed with this source code.
6+
*/
7+
8+
9+
#import <YYCache/YYCache.h>
10+
#import <SDWebImage/SDWebImage.h>
11+
12+
// YYCache category to support `SDImageCache` protocol. This allow user who prefer YYCache to be used as SDWebImage's custom image cache
13+
14+
@interface YYCache (SDAddtions) <SDImageCache>
15+
16+
@end
Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
/*
2+
* This file is part of the SDWebImage-YYCache package.
3+
*
4+
* For the full copyright and license information, please view the LICENSE
5+
* file that was distributed with this source code.
6+
*/
7+
8+
9+
#import "YYCache+SDAddtions.h"
10+
#import "YYMemoryCache+SDAddtions.h"
11+
#import "YYDiskCache+SDAddtions.h"
12+
13+
static NSData * SDYYPluginCacheDataWithImageData(UIImage *image, NSData *imageData) {
14+
NSData *data = imageData;
15+
if (!data && image) {
16+
// If we do not have any data to detect image format, check whether it contains alpha channel to use PNG or JPEG format
17+
SDImageFormat format;
18+
if ([SDImageCoderHelper CGImageContainsAlpha:image.CGImage]) {
19+
format = SDImageFormatPNG;
20+
} else {
21+
format = SDImageFormatJPEG;
22+
}
23+
data = [[SDImageCodersManager sharedManager] encodedDataWithImage:image format:format options:nil];
24+
}
25+
26+
return data;
27+
}
28+
29+
@implementation YYCache (SDAddtions)
30+
31+
- (id<SDWebImageOperation>)queryImageForKey:(NSString *)key options:(SDWebImageOptions)options context:(SDWebImageContext *)context completion:(SDImageCacheQueryCompletionBlock)completionBlock {
32+
if (!key) {
33+
if (completionBlock) {
34+
completionBlock(nil, nil, SDImageCacheTypeNone);
35+
}
36+
return nil;
37+
}
38+
39+
// First check the in-memory cache...
40+
UIImage *image = [self.memoryCache objectForKey:key];
41+
BOOL shouldQueryMemoryOnly = ([image isKindOfClass:[UIImage class]] && !(options & SDImageCacheQueryDataWhenInMemory));
42+
if (shouldQueryMemoryOnly) {
43+
if (completionBlock) {
44+
completionBlock(image, nil, SDImageCacheTypeMemory);
45+
}
46+
return nil;
47+
}
48+
49+
NSOperation *operation = [NSOperation new];
50+
void(^queryDiskBlock)(NSData *) = ^(NSData *diskData){
51+
if (operation.isCancelled) {
52+
// do not call the completion if cancelled
53+
return;
54+
}
55+
56+
@autoreleasepool {
57+
UIImage *diskImage;
58+
SDImageCacheType cacheType = SDImageCacheTypeDisk;
59+
if (image) {
60+
// the image is from in-memory cache
61+
diskImage = image;
62+
cacheType = SDImageCacheTypeMemory;
63+
} else if (diskData) {
64+
NSString *cacheKey = key;
65+
if ([context valueForKey:SDWebImageContextImageTransformer]) {
66+
// grab the transformed disk image if transformer provided
67+
id<SDImageTransformer> transformer = [context valueForKey:SDWebImageContextImageTransformer];
68+
NSString *transformerKey = [transformer transformerKey];
69+
cacheKey = SDTransformedKeyForKey(key, transformerKey);
70+
}
71+
// decode image data only if in-memory cache missed
72+
diskImage = SDImageCacheDecodeImageData(diskData, key, options, context);
73+
if (diskImage) {
74+
NSUInteger cost = SDMemoryCacheCostForImage(diskImage);
75+
[self.memoryCache setObject:diskImage forKey:key cost:cost];
76+
}
77+
}
78+
79+
if (completionBlock) {
80+
if (options & SDImageCacheQueryDiskSync) {
81+
completionBlock(diskImage, diskData, cacheType);
82+
} else {
83+
dispatch_async(dispatch_get_main_queue(), ^{
84+
completionBlock(diskImage, diskData, cacheType);
85+
});
86+
}
87+
}
88+
}
89+
};
90+
91+
if (options & SDImageCacheQueryDiskSync) {
92+
NSData *diskData = [self.diskCache dataForKey:key];
93+
queryDiskBlock(diskData);
94+
} else {
95+
// YYDiskCache's completion block is called in the global queue
96+
[self.diskCache objectForKey:key withBlock:^(NSString * _Nonnull key, NSObject<NSCoding> * _Nullable object) {
97+
NSData *diskData = nil;
98+
if ([object isKindOfClass:[NSData class]]) {
99+
diskData = (NSData *)object;
100+
}
101+
queryDiskBlock(diskData);
102+
}];
103+
}
104+
105+
return operation;
106+
}
107+
108+
- (void)storeImage:(UIImage *)image imageData:(NSData *)imageData forKey:(NSString *)key cacheType:(SDImageCacheType)cacheType completion:(SDWebImageNoParamsBlock)completionBlock {
109+
switch (cacheType) {
110+
case SDImageCacheTypeNone: {
111+
if (completionBlock) {
112+
completionBlock();
113+
}
114+
}
115+
break;
116+
case SDImageCacheTypeMemory: {
117+
NSUInteger cost = SDMemoryCacheCostForImage(image);
118+
[self.memoryCache setObject:image forKey:key cost:cost];
119+
}
120+
break;
121+
case SDImageCacheTypeDisk: {
122+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
123+
NSData *data = SDYYPluginCacheDataWithImageData(image, imageData);
124+
if (!data) {
125+
// SDImageCache does not remove object if `data` is nil
126+
if (completionBlock) {
127+
dispatch_async(dispatch_get_main_queue(), ^{
128+
completionBlock();
129+
});
130+
}
131+
}
132+
[self.diskCache setObject:data forKey:key withBlock:^{
133+
if (completionBlock) {
134+
dispatch_async(dispatch_get_main_queue(), ^{
135+
completionBlock();
136+
});
137+
}
138+
}];
139+
});
140+
}
141+
break;
142+
case SDImageCacheTypeAll: {
143+
NSUInteger cost = SDMemoryCacheCostForImage(image);
144+
[self.memoryCache setObject:image forKey:key cost:cost];
145+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
146+
NSData *data = SDYYPluginCacheDataWithImageData(image, imageData);
147+
if (!data) {
148+
// SDImageCache does not remove object if `data` is nil
149+
if (completionBlock) {
150+
dispatch_async(dispatch_get_main_queue(), ^{
151+
completionBlock();
152+
});
153+
}
154+
}
155+
[self.diskCache setObject:data forKey:key withBlock:^{
156+
if (completionBlock) {
157+
dispatch_async(dispatch_get_main_queue(), ^{
158+
completionBlock();
159+
});
160+
}
161+
}];
162+
});
163+
}
164+
break;
165+
default: {
166+
if (completionBlock) {
167+
completionBlock();
168+
}
169+
}
170+
break;
171+
}
172+
}
173+
174+
- (void)removeImageForKey:(NSString *)key cacheType:(SDImageCacheType)cacheType completion:(SDWebImageNoParamsBlock)completionBlock {
175+
switch (cacheType) {
176+
case SDImageCacheTypeNone: {
177+
if (completionBlock) {
178+
completionBlock();
179+
}
180+
}
181+
break;
182+
case SDImageCacheTypeMemory: {
183+
[self.memoryCache removeObjectForKey:key];
184+
if (completionBlock) {
185+
completionBlock();
186+
}
187+
}
188+
break;
189+
case SDImageCacheTypeDisk: {
190+
[self.diskCache removeObjectForKey:key withBlock:^(NSString * _Nonnull key) {
191+
if (completionBlock) {
192+
dispatch_async(dispatch_get_main_queue(), ^{
193+
completionBlock();
194+
});
195+
}
196+
}];
197+
}
198+
break;
199+
case SDImageCacheTypeAll: {
200+
[self.memoryCache removeObjectForKey:key];
201+
[self.diskCache removeObjectForKey:key withBlock:^(NSString * _Nonnull key) {
202+
if (completionBlock) {
203+
dispatch_async(dispatch_get_main_queue(), ^{
204+
completionBlock();
205+
});
206+
}
207+
}];
208+
}
209+
break;
210+
default: {
211+
if (completionBlock) {
212+
completionBlock();
213+
}
214+
}
215+
break;
216+
}
217+
}
218+
219+
- (void)containsImageForKey:(NSString *)key cacheType:(SDImageCacheType)cacheType completion:(SDImageCacheContainsCompletionBlock)completionBlock {
220+
switch (cacheType) {
221+
case SDImageCacheTypeNone: {
222+
if (completionBlock) {
223+
completionBlock(SDImageCacheTypeNone);
224+
}
225+
}
226+
break;
227+
case SDImageCacheTypeMemory: {
228+
BOOL isInMemoryCache = ([self.memoryCache objectForKey:key] != nil);
229+
if (completionBlock) {
230+
completionBlock(isInMemoryCache ? SDImageCacheTypeMemory : SDImageCacheTypeNone);
231+
}
232+
}
233+
break;
234+
case SDImageCacheTypeDisk: {
235+
[self.diskCache containsObjectForKey:key withBlock:^(NSString * _Nonnull key, BOOL contains) {
236+
if (completionBlock) {
237+
dispatch_async(dispatch_get_main_queue(), ^{
238+
completionBlock(contains ? SDImageCacheTypeDisk : SDImageCacheTypeNone);
239+
});
240+
}
241+
}];
242+
}
243+
break;
244+
case SDImageCacheTypeAll: {
245+
BOOL isInMemoryCache = ([self.memoryCache objectForKey:key] != nil);
246+
if (isInMemoryCache) {
247+
if (completionBlock) {
248+
completionBlock(SDImageCacheTypeMemory);
249+
}
250+
return;
251+
}
252+
[self.diskCache containsObjectForKey:key withBlock:^(NSString * _Nonnull key, BOOL contains) {
253+
if (completionBlock) {
254+
dispatch_async(dispatch_get_main_queue(), ^{
255+
completionBlock(contains ? SDImageCacheTypeDisk : SDImageCacheTypeNone);
256+
});
257+
}
258+
}];
259+
}
260+
break;
261+
default:
262+
if (completionBlock) {
263+
completionBlock(SDImageCacheTypeNone);
264+
}
265+
break;
266+
}
267+
}
268+
269+
- (void)clearWithCacheType:(SDImageCacheType)cacheType completion:(SDWebImageNoParamsBlock)completionBlock {
270+
switch (cacheType) {
271+
case SDImageCacheTypeNone: {
272+
if (completionBlock) {
273+
completionBlock();
274+
}
275+
return;
276+
}
277+
break;
278+
case SDImageCacheTypeMemory: {
279+
[self.memoryCache removeAllObjects];
280+
if (completionBlock) {
281+
completionBlock();
282+
}
283+
}
284+
break;
285+
case SDImageCacheTypeDisk: {
286+
[self.diskCache removeAllObjectsWithBlock:^{
287+
if (completionBlock) {
288+
dispatch_async(dispatch_get_main_queue(), ^{
289+
completionBlock();
290+
});
291+
}
292+
}];
293+
}
294+
break;
295+
case SDImageCacheTypeAll: {
296+
[self.memoryCache removeAllObjects];
297+
[self.diskCache removeAllObjectsWithBlock:^{
298+
if (completionBlock) {
299+
dispatch_async(dispatch_get_main_queue(), ^{
300+
completionBlock();
301+
});
302+
}
303+
}];
304+
}
305+
break;
306+
default: {
307+
if (completionBlock) {
308+
completionBlock();
309+
}
310+
}
311+
break;
312+
}
313+
}
314+
315+
@end

SDWebImageYYPlugin/Module/SDWebImageYYPlugin.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
#endif
1212

1313
// YYCache
14-
#if __has_include(<SDWebImageYYPlugin/YYDiskCache+SDAddtions.h>)
15-
#import <SDWebImageYYPlugin/YYDiskCache+SDAddtions.h>
14+
#if __has_include(<SDWebImageYYPlugin/YYCache+SDAddtions.h>)
15+
#import <SDWebImageYYPlugin/YYCache+SDAddtions.h>
1616
#import <SDWebImageYYPlugin/YYMemoryCache+SDAddtions.h>
17+
#import <SDWebImageYYPlugin/YYDiskCache+SDAddtions.h>
1718
#endif
1819

1920
// YYImage

0 commit comments

Comments
 (0)