Closed xzilja closed 5 years ago
@IljaDaderko If you're careful, there are a new series of method inSDImageCache
protocol method.
containsImageForKey:cacheType:completion. The input cacheType is your desired cache to check, the output cacheType is where we found. (For example you can input .all
and we output .disk
)
And also, there is the exisiting method in SDImageCache
class, the imageFromMemoryCacheForKey:. Because for now, the memory cache only contains the image instance. So actually, the check
is equal to the cost of query memory
, they're the same design like NSDictionary.objectForKey:
.
You can use the demo code to check
SDImageCache *cache;
NSArray<NSString *> *keys;
[keys enumerateObjectsUsingBlock:^(NSString * _Nonnull key, NSUInteger idx, BOOL * _Nonnull stop) {
BOOL isInMemoryCache = ([cache imageFromMemoryCacheForKey:key] != nil);
}];
or this, to works for your custom cache protocol in 5.0 (Such as YYCache)
id<SDImageCache> cache;
NSArray<NSString *> *keys;
[keys enumerateObjectsUsingBlock:^(NSString * _Nonnull key, NSUInteger idx, BOOL * _Nonnull stop) {
__block SDImageCacheType cacheType;
[cache containsImageForKey:key cacheType:SDImageCacheTypeMemory completion:^(SDImageCacheType containsCacheType) {
cacheType = containsCacheType;
}]
BOOL isInMemoryCache = cacheType == SDImageCacheTypeMemory;
}];
cacheKeyForUrl
is in the manager method. It's used to grab the generated cache key for URL during load. Because not always the URL.absoluteString == cacheKey
.
We supports the Cache Key Filter to provide a cutsom key, to help user to provide the high-level fucntion, like the CDN lookup (for example, differnt URL www.1.foo.com/1.jpg, www.2.foo.com/1.jpg is 2 CDN image url, they can match to same cache key, instead of duplicated download and cache).
Assuming I don't initially know they key for the url (for example I get array of urls from API response) and want to check if all of them are in cache.
I will need to run a loop that combines cacheKeyForUrl
and imageFromMemoryCacheForKey
for example?
This far this is my attempt (it's within react-native scope hence RTC
and resolve / reject
)
RCT_EXPORT_METHOD(checkCache
: (NSArray<NSURL *> *)urls resolver
: (RCTPromiseResolveBlock)resolve rejecter
: (RCTPromiseRejectBlock)reject) {
__block BOOL cacheExists = YES;
@try {
[urls enumerateObjectsUsingBlock:^(NSURL *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {
NSString *key = nil;
key = [[SDWebImageManager sharedManager] cacheKeyForURL:obj];
if (key != nil) {
[[SDImageCache sharedImageCache]
containsImageForKey:key
cacheType:SDImageCacheTypeMemory
completion:^(SDImageCacheType containsCacheType) {
if (containsCacheType != SDImageCacheTypeMemory) {
cacheExists = NO;
*stop = YES;
}
}];
} else {
*stop = YES;
}
}];
resolve(@{@"cacheExists" : @(cacheExists)});
} @catch (NSError *error) {
reject(@"ASQImage:unknown_error", @"chechCache method failed", error);
}
}
Did I grasp this concept correctly? At first glance this seems to be working in my app 👍
[SDImageCache sharedImageCache]
. If you desired to only use SDImageCache
but not other custom cache implementation. You can directly use the imageFromMemoryCacheForKey:
API. This don't need a block like that containsImageForKey:
protocol method.
Just for-in loop to call this. And collect the result and callback.
But actually, I don't think this is a good React Native Bridge. Consider the user-side of your bridge API.
I can provide a list of url, but you give me a bool value represent the existing. It's ok when I see a true
callback. But what to do if I receive a false
? I don't know which URL cache is missing, which is hit.
A better design of this API, should return a hash object. Like this:
[{
key: "www.foobar.com/1.jpg",
exist: false
},
{
key: "www.foobar.com/2.jpg",
exist: true
},
]
Which may be better. Or if you don't care the bridge callback performance (I remember the React Native briding need JavaScriptCore in another thread), you can receive just one URL and callback whether it exists.
Ah, I didn't realise url is the key, thought it was something custom. This makes sense. In terms of the bridge perfromance, it's just an async function on js side and within ObjC we only return it one time after the loop (not on every loop run).
I will indeed implement approach that returns array of keys and exist flags like you suggested 👍 Thank you for explaing all of this!
New Issue Checklist
Issue Info
Issue Description and Steps
Using SDWebImage v5 what is the least costly method to check if array of urls exists in memory cache in a synchronous?
While looking through documentation closest thing I found for this use case is cacheKeyForUrl that I believe can be used in a loop to check each url in the array individually and if one of them does not return a key, we can assume that full array is not in the cache.
However, what if I only want to check memory, without hitting disk cache?
Perhaps I am missing something, a helper to check if link(s) are in memory?