Skip to content

Commit

Permalink
Implement Image.queryCache on iOS (facebook#18782)
Browse files Browse the repository at this point in the history
Summary:
The API was available only on Android (with no mention to that effect in the docs, AFAICT).
This commit adds a simple iOS implementation based on NSURLCache. It should be possible to
query the decoded image cache as well to provide higher fidelity (i.e. "disk", "memory",
"decoded") if the caller passes size, scale, etc. in addition to the image URL, but it's
probably not worth the complexity. The assumption is that callers are interested in the
durability rather than performance aspect of the returned information.

Tested with RNTester on iPhone emulator.

[IOS] [ENHANCEMENT] [Image] - Implemented queryCache
Pull Request resolved: facebook#18782

Differential Revision: D9411533

Pulled By: hramos

fbshipit-source-id: b430263959bb5f9b8ed9e28bb0a95f8879df881a
  • Loading branch information
ladipro authored and facebook-github-bot committed Aug 20, 2018
1 parent b97e94e commit ebbd56b
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 0 deletions.
12 changes: 12 additions & 0 deletions Libraries/Image/Image.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,16 @@ function prefetch(url: string) {
return ImageViewManager.prefetchImage(url);
}

async function queryCache(urls: Array<string>): Promise<Map<string, 'memory' | 'disk'>> {
return await ImageViewManager.queryCache(urls);
}

declare class ImageComponentType extends ReactNative.NativeComponent<
ImagePropsType,
> {
static getSize: typeof getSize;
static prefetch: typeof prefetch;
static queryCache: typeof queryCache;
static resolveAssetSource: typeof resolveAssetSource;
static propTypes: typeof ImageProps;
}
Expand Down Expand Up @@ -133,6 +138,13 @@ Image.getSize = getSize;
*/
Image.prefetch = prefetch;

/**
* Performs cache interrogation.
*
* See https://facebook.github.io/react-native/docs/image.html#querycache
*/
Image.queryCache = queryCache;

/**
* Resolves an asset reference into an object.
*
Expand Down
8 changes: 8 additions & 0 deletions Libraries/Image/RCTImageLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ typedef dispatch_block_t RCTImageLoaderCancellationBlock;
*/
- (RCTImageLoaderCancellationBlock)getImageSizeForURLRequest:(NSURLRequest *)imageURLRequest
block:(void(^)(NSError *error, CGSize size))completionBlock;
/**
* Determines whether given image URLs are cached locally. The `requests` array is expected
* to contain objects convertible to NSURLRequest. The return value maps URLs to strings:
* "disk" for images known to be cached in non-volatile storage, "memory" for images known
* to be cached in memory. Dictionary items corresponding to images that are not known to be
* cached are simply missing.
*/
- (NSDictionary *)getImageCacheStatus:(NSArray *)requests;

/**
* Allows developers to set their own caching implementation for
Expand Down
19 changes: 19 additions & 0 deletions Libraries/Image/RCTImageLoader.m
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,25 @@ - (RCTImageLoaderCancellationBlock)getImageSizeForURLRequest:(NSURLRequest *)ima
completionBlock:completion];
}

- (NSDictionary *)getImageCacheStatus:(NSArray *)requests
{
NSMutableDictionary *results = [NSMutableDictionary dictionary];
for (id request in requests) {
NSURLRequest *urlRequest = [RCTConvert NSURLRequest:request];
if (urlRequest) {
NSCachedURLResponse *cachedResponse = [NSURLCache.sharedURLCache cachedResponseForRequest:urlRequest];
if (cachedResponse) {
if (cachedResponse.storagePolicy == NSURLCacheStorageAllowedInMemoryOnly) {
[results setObject:@"memory" forKey:urlRequest.URL.absoluteString];
} else {
[results setObject:@"disk" forKey:urlRequest.URL.absoluteString];
}
}
}
}
return results;
}

#pragma mark - RCTURLRequestHandler

- (BOOL)canHandleRequest:(NSURLRequest *)request
Expand Down
7 changes: 7 additions & 0 deletions Libraries/Image/RCTImageViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,11 @@ - (UIView *)view
}];
}

RCT_EXPORT_METHOD(queryCache:(NSArray *)requests
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
{
resolve([self.bridge.imageLoader getImageCacheStatus:requests]);
}

@end
12 changes: 12 additions & 0 deletions RNTester/js/ImageExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ var NetworkImageCallbackExample = createReactClass({
this._loadEventFired(
`✔ Prefetch OK (+${new Date() - mountTime}ms)`,
);
Image.queryCache([IMAGE_PREFETCH_URL]).then((map) => {
var result = map.get(IMAGE_PREFETCH_URL);
if (result) {
this._loadEventFired(
`✔ queryCache "${result}" (+${new Date() - mountTime}ms)`,
);
} else {
this._loadEventFired(
`✘ queryCache (+${new Date() - mountTime}ms)`,
);
}
});
},
error => {
this._loadEventFired(
Expand Down

0 comments on commit ebbd56b

Please sign in to comment.