mirror of
https://github.com/status-im/react-native.git
synced 2025-02-25 07:35:25 +00:00
[React Native] Update image downloader
Summary: Change `RCTImageDownloader` so it stores the `RCTDownloadTaskWrapper` for reuse. Modify `RCTDownloadTaskWrapper` to use associated objects to store the completion/progress blocks.
This commit is contained in:
parent
8e70c7f003
commit
72b50dc32d
@ -14,13 +14,8 @@ typedef void (^RCTDataProgressBlock)(int64_t written, int64_t total);
|
|||||||
|
|
||||||
@interface RCTDownloadTaskWrapper : NSObject <NSURLSessionDownloadDelegate>
|
@interface RCTDownloadTaskWrapper : NSObject <NSURLSessionDownloadDelegate>
|
||||||
|
|
||||||
@property (copy, nonatomic) RCTDataCompletionBlock completionBlock;
|
|
||||||
@property (copy, nonatomic) RCTDataProgressBlock progressBlock;
|
|
||||||
|
|
||||||
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration delegateQueue:(NSOperationQueue *)delegateQueue;
|
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration delegateQueue:(NSOperationQueue *)delegateQueue;
|
||||||
|
|
||||||
- (NSURLSessionDownloadTask *)downloadData:(NSURL *)url progressBlock:(RCTDataProgressBlock)progressBlock completionBlock:(RCTDataCompletionBlock)completionBlock;
|
- (NSURLSessionDownloadTask *)downloadData:(NSURL *)url progressBlock:(RCTDataProgressBlock)progressBlock completionBlock:(RCTDataCompletionBlock)completionBlock;
|
||||||
|
|
||||||
@property (nonatomic, assign) id<NSURLSessionDownloadDelegate> delegate;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -10,6 +10,42 @@
|
|||||||
|
|
||||||
#import "RCTDownloadTaskWrapper.h"
|
#import "RCTDownloadTaskWrapper.h"
|
||||||
|
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
|
static void *const RCTDownloadTaskWrapperCompletionBlockKey = (void *)&RCTDownloadTaskWrapperCompletionBlockKey;
|
||||||
|
static void *const RCTDownloadTaskWrapperProgressBlockKey = (void *)&RCTDownloadTaskWrapperProgressBlockKey;
|
||||||
|
|
||||||
|
@interface NSURLSessionTask (RCTDownloadTaskWrapper)
|
||||||
|
|
||||||
|
@property (nonatomic, copy, setter=rct_setCompletionBlock:) RCTDataCompletionBlock rct_completionBlock;
|
||||||
|
@property (nonatomic, copy, setter=rct_setProgressBlock:) RCTDataProgressBlock rct_progressBlock;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation NSURLSessionTask (RCTDownloadTaskWrapper)
|
||||||
|
|
||||||
|
- (RCTDataCompletionBlock)rct_completionBlock
|
||||||
|
{
|
||||||
|
return objc_getAssociatedObject(self, RCTDownloadTaskWrapperCompletionBlockKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)rct_setCompletionBlock:(RCTDataCompletionBlock)completionBlock
|
||||||
|
{
|
||||||
|
objc_setAssociatedObject(self, RCTDownloadTaskWrapperCompletionBlockKey, completionBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (RCTDataProgressBlock)rct_progressBlock
|
||||||
|
{
|
||||||
|
return objc_getAssociatedObject(self, RCTDownloadTaskWrapperProgressBlockKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)rct_setProgressBlock:(RCTDataProgressBlock)progressBlock
|
||||||
|
{
|
||||||
|
objc_setAssociatedObject(self, RCTDownloadTaskWrapperProgressBlockKey, progressBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation RCTDownloadTaskWrapper
|
@implementation RCTDownloadTaskWrapper
|
||||||
{
|
{
|
||||||
NSURLSession *_URLSession;
|
NSURLSession *_URLSession;
|
||||||
@ -26,10 +62,10 @@
|
|||||||
|
|
||||||
- (NSURLSessionDownloadTask *)downloadData:(NSURL *)url progressBlock:(RCTDataProgressBlock)progressBlock completionBlock:(RCTDataCompletionBlock)completionBlock
|
- (NSURLSessionDownloadTask *)downloadData:(NSURL *)url progressBlock:(RCTDataProgressBlock)progressBlock completionBlock:(RCTDataCompletionBlock)completionBlock
|
||||||
{
|
{
|
||||||
self.completionBlock = completionBlock;
|
|
||||||
self.progressBlock = progressBlock;
|
|
||||||
|
|
||||||
NSURLSessionDownloadTask *task = [_URLSession downloadTaskWithURL:url completionHandler:nil];
|
NSURLSessionDownloadTask *task = [_URLSession downloadTaskWithURL:url completionHandler:nil];
|
||||||
|
task.rct_completionBlock = completionBlock;
|
||||||
|
task.rct_progressBlock = progressBlock;
|
||||||
|
|
||||||
[task resume];
|
[task resume];
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
@ -38,30 +74,28 @@
|
|||||||
|
|
||||||
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
|
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
|
||||||
{
|
{
|
||||||
if (self.completionBlock) {
|
if (downloadTask.rct_completionBlock) {
|
||||||
NSData *data = [NSData dataWithContentsOfURL:location];
|
NSData *data = [NSData dataWithContentsOfURL:location];
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
self.completionBlock(downloadTask.response, data, nil);
|
downloadTask.rct_completionBlock(downloadTask.response, data, nil);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)didWriteData totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;
|
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)didWriteData totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;
|
||||||
{
|
{
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
if (downloadTask.rct_progressBlock) {
|
||||||
if (self.progressBlock != nil) {
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
self.progressBlock(totalBytesWritten, totalBytesExpectedToWrite);
|
downloadTask.rct_progressBlock(totalBytesWritten, totalBytesExpectedToWrite);
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)URLSession:(NSURLSession *)session
|
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
|
||||||
task:(NSURLSessionTask *)task
|
|
||||||
didCompleteWithError:(NSError *)error
|
|
||||||
{
|
{
|
||||||
if (error && self.completionBlock) {
|
if (error && task.rct_completionBlock) {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
self.completionBlock(NULL, NULL, error);
|
task.rct_completionBlock(nil, nil, error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
typedef void (^RCTDataDownloadBlock)(NSData *data, NSError *error);
|
typedef void (^RCTDataDownloadBlock)(NSData *data, NSError *error);
|
||||||
typedef void (^RCTImageDownloadBlock)(UIImage *image, NSError *error);
|
typedef void (^RCTImageDownloadBlock)(UIImage *image, NSError *error);
|
||||||
|
typedef void (^RCTImageDownloadCancellationBlock)(void);
|
||||||
|
|
||||||
@interface RCTImageDownloader : NSObject
|
@interface RCTImageDownloader : NSObject
|
||||||
|
|
||||||
@ -23,9 +24,9 @@ typedef void (^RCTImageDownloadBlock)(UIImage *image, NSError *error);
|
|||||||
* will not be executed on the same thread you called the method from, nor on
|
* will not be executed on the same thread you called the method from, nor on
|
||||||
* the main thread. Returns a token that can be used to cancel the download.
|
* the main thread. Returns a token that can be used to cancel the download.
|
||||||
*/
|
*/
|
||||||
- (id)downloadDataForURL:(NSURL *)url
|
- (RCTImageDownloadCancellationBlock)downloadDataForURL:(NSURL *)url
|
||||||
progressBlock:(RCTDataProgressBlock)progressBlock
|
progressBlock:(RCTDataProgressBlock)progressBlock
|
||||||
block:(RCTDataDownloadBlock)block;
|
block:(RCTDataDownloadBlock)block;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Downloads an image and decompresses it a the size specified. The compressed
|
* Downloads an image and decompresses it a the size specified. The compressed
|
||||||
@ -33,19 +34,19 @@ typedef void (^RCTImageDownloadBlock)(UIImage *image, NSError *error);
|
|||||||
* will not be executed on the same thread you called the method from, nor on
|
* will not be executed on the same thread you called the method from, nor on
|
||||||
* the main thread. Returns a token that can be used to cancel the download.
|
* the main thread. Returns a token that can be used to cancel the download.
|
||||||
*/
|
*/
|
||||||
- (id)downloadImageForURL:(NSURL *)url
|
- (RCTImageDownloadCancellationBlock)downloadImageForURL:(NSURL *)url
|
||||||
size:(CGSize)size
|
size:(CGSize)size
|
||||||
scale:(CGFloat)scale
|
scale:(CGFloat)scale
|
||||||
resizeMode:(UIViewContentMode)resizeMode
|
resizeMode:(UIViewContentMode)resizeMode
|
||||||
backgroundColor:(UIColor *)backgroundColor
|
backgroundColor:(UIColor *)backgroundColor
|
||||||
progressBlock:(RCTDataProgressBlock)progressBlock
|
progressBlock:(RCTDataProgressBlock)progressBlock
|
||||||
block:(RCTImageDownloadBlock)block;
|
block:(RCTImageDownloadBlock)block;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancel an in-flight download. If multiple requets have been made for the
|
* Cancel an in-flight download. If multiple requets have been made for the
|
||||||
* same image, only the request that relates to the token passed will be
|
* same image, only the request that relates to the token passed will be
|
||||||
* cancelled.
|
* cancelled.
|
||||||
*/
|
*/
|
||||||
- (void)cancelDownload:(id)downloadToken;
|
- (void)cancelDownload:(RCTImageDownloadCancellationBlock)downloadToken;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -23,6 +23,7 @@ CGRect RCTClipRect(CGSize, CGFloat, CGSize, CGFloat, UIViewContentMode);
|
|||||||
NSURLCache *_cache;
|
NSURLCache *_cache;
|
||||||
dispatch_queue_t _processingQueue;
|
dispatch_queue_t _processingQueue;
|
||||||
NSMutableDictionary *_pendingBlocks;
|
NSMutableDictionary *_pendingBlocks;
|
||||||
|
RCTDownloadTaskWrapper *_downloadTaskWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (RCTImageDownloader *)sharedInstance
|
+ (RCTImageDownloader *)sharedInstance
|
||||||
@ -41,22 +42,22 @@ CGRect RCTClipRect(CGSize, CGFloat, CGSize, CGFloat, UIViewContentMode);
|
|||||||
_cache = [[NSURLCache alloc] initWithMemoryCapacity:5 * 1024 * 1024 diskCapacity:200 * 1024 * 1024 diskPath:@"React/RCTImageDownloader"];
|
_cache = [[NSURLCache alloc] initWithMemoryCapacity:5 * 1024 * 1024 diskCapacity:200 * 1024 * 1024 diskPath:@"React/RCTImageDownloader"];
|
||||||
_processingQueue = dispatch_queue_create("com.facebook.React.DownloadProcessingQueue", DISPATCH_QUEUE_SERIAL);
|
_processingQueue = dispatch_queue_create("com.facebook.React.DownloadProcessingQueue", DISPATCH_QUEUE_SERIAL);
|
||||||
_pendingBlocks = [[NSMutableDictionary alloc] init];
|
_pendingBlocks = [[NSMutableDictionary alloc] init];
|
||||||
|
|
||||||
|
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
|
||||||
|
_downloadTaskWrapper = [[RCTDownloadTaskWrapper alloc] initWithSessionConfiguration:config delegateQueue:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)_downloadDataForURL:(NSURL *)url progressBlock:progressBlock block:(RCTCachedDataDownloadBlock)block
|
- (RCTImageDownloadCancellationBlock)_downloadDataForURL:(NSURL *)url progressBlock:progressBlock block:(RCTCachedDataDownloadBlock)block
|
||||||
{
|
{
|
||||||
NSString *cacheKey = url.absoluteString;
|
NSString *const cacheKey = url.absoluteString;
|
||||||
|
|
||||||
__block BOOL cancelled = NO;
|
__block BOOL cancelled = NO;
|
||||||
__block NSURLSessionDownloadTask *task = nil;
|
__block NSURLSessionDownloadTask *task = nil;
|
||||||
|
|
||||||
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
|
RCTImageDownloadCancellationBlock cancel = ^{
|
||||||
RCTDownloadTaskWrapper *downloadTaskWrapper = [[RCTDownloadTaskWrapper alloc] initWithSessionConfiguration:config delegateQueue:nil];
|
|
||||||
|
|
||||||
dispatch_block_t cancel = ^{
|
|
||||||
cancelled = YES;
|
cancelled = YES;
|
||||||
|
|
||||||
dispatch_async(_processingQueue, ^{
|
dispatch_async(_processingQueue, ^{
|
||||||
@ -90,7 +91,7 @@ CGRect RCTClipRect(CGSize, CGFloat, CGSize, CGFloat, UIViewContentMode);
|
|||||||
};
|
};
|
||||||
|
|
||||||
NSURLRequest *request = [NSURLRequest requestWithURL:url];
|
NSURLRequest *request = [NSURLRequest requestWithURL:url];
|
||||||
task = [downloadTaskWrapper downloadData:url progressBlock:progressBlock completionBlock:^(NSURLResponse *response, NSData *data, NSError *error) {
|
task = [_downloadTaskWrapper downloadData:url progressBlock:progressBlock completionBlock:^(NSURLResponse *response, NSData *data, NSError *error) {
|
||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
runBlocks(NO, data, error);
|
runBlocks(NO, data, error);
|
||||||
}
|
}
|
||||||
@ -120,20 +121,20 @@ CGRect RCTClipRect(CGSize, CGFloat, CGSize, CGFloat, UIViewContentMode);
|
|||||||
return [cancel copy];
|
return [cancel copy];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)downloadDataForURL:(NSURL *)url progressBlock:(RCTDataProgressBlock)progressBlock block:(RCTDataDownloadBlock)block
|
- (RCTImageDownloadCancellationBlock)downloadDataForURL:(NSURL *)url progressBlock:(RCTDataProgressBlock)progressBlock block:(RCTDataDownloadBlock)block
|
||||||
{
|
{
|
||||||
return [self _downloadDataForURL:url progressBlock:progressBlock block:^(BOOL cached, NSData *data, NSError *error) {
|
return [self _downloadDataForURL:url progressBlock:progressBlock block:^(BOOL cached, NSData *data, NSError *error) {
|
||||||
block(data, error);
|
block(data, error);
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)downloadImageForURL:(NSURL *)url
|
- (RCTImageDownloadCancellationBlock)downloadImageForURL:(NSURL *)url
|
||||||
size:(CGSize)size
|
size:(CGSize)size
|
||||||
scale:(CGFloat)scale
|
scale:(CGFloat)scale
|
||||||
resizeMode:(UIViewContentMode)resizeMode
|
resizeMode:(UIViewContentMode)resizeMode
|
||||||
backgroundColor:(UIColor *)backgroundColor
|
backgroundColor:(UIColor *)backgroundColor
|
||||||
progressBlock:(RCTDataProgressBlock)progressBlock
|
progressBlock:(RCTDataProgressBlock)progressBlock
|
||||||
block:(RCTImageDownloadBlock)block
|
block:(RCTImageDownloadBlock)block
|
||||||
{
|
{
|
||||||
return [self downloadDataForURL:url progressBlock:progressBlock block:^(NSData *data, NSError *error) {
|
return [self downloadDataForURL:url progressBlock:progressBlock block:^(NSData *data, NSError *error) {
|
||||||
if (!data || error) {
|
if (!data || error) {
|
||||||
@ -182,10 +183,10 @@ CGRect RCTClipRect(CGSize, CGFloat, CGSize, CGFloat, UIViewContentMode);
|
|||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)cancelDownload:(id)downloadToken
|
- (void)cancelDownload:(RCTImageDownloadCancellationBlock)downloadToken
|
||||||
{
|
{
|
||||||
if (downloadToken) {
|
if (downloadToken) {
|
||||||
((dispatch_block_t)downloadToken)();
|
downloadToken();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user