From 2c5290946bd7d06fc4138b8c7ffd2061a55d401d Mon Sep 17 00:00:00 2001 From: Nick Lockwood Date: Mon, 27 Jul 2015 08:48:31 -0700 Subject: [PATCH] Converted RCTImageLoader to be a bridge module --- Libraries/Image/RCTCameraRollManager.m | 6 ++-- Libraries/Image/RCTImageLoader.h | 36 +++++++++++-------- Libraries/Image/RCTImageLoader.m | 44 ++++++++++++++++-------- Libraries/Image/RCTImageRequestHandler.m | 15 +++++--- Libraries/Image/RCTImageView.m | 13 ++++--- 5 files changed, 71 insertions(+), 43 deletions(-) diff --git a/Libraries/Image/RCTCameraRollManager.m b/Libraries/Image/RCTCameraRollManager.m index 3d331a8f1..d28198ac0 100644 --- a/Libraries/Image/RCTCameraRollManager.m +++ b/Libraries/Image/RCTCameraRollManager.m @@ -29,12 +29,12 @@ RCT_EXPORT_METHOD(saveImageWithTag:(NSString *)imageTag successCallback:(RCTResponseSenderBlock)successCallback errorCallback:(RCTResponseErrorBlock)errorCallback) { - [RCTImageLoader loadImageWithTag:imageTag bridge:_bridge callback:^(NSError *loadError, UIImage *loadedImage) { + [_bridge.imageLoader loadImageWithTag:imageTag callback:^(NSError *loadError, UIImage *loadedImage) { if (loadError) { errorCallback(loadError); return; } - [[RCTImageLoader assetsLibrary] writeImageToSavedPhotosAlbum:[loadedImage CGImage] metadata:nil completionBlock:^(NSURL *assetURL, NSError *saveError) { + [_bridge.assetsLibrary writeImageToSavedPhotosAlbum:[loadedImage CGImage] metadata:nil completionBlock:^(NSURL *assetURL, NSError *saveError) { if (saveError) { RCTLogWarn(@"Error saving cropped image: %@", saveError); errorCallback(saveError); @@ -96,7 +96,7 @@ RCT_EXPORT_METHOD(getPhotos:(NSDictionary *)params BOOL __block calledCallback = NO; NSMutableArray *assets = [[NSMutableArray alloc] init]; - [[RCTImageLoader assetsLibrary] enumerateGroupsWithTypes:groupTypes usingBlock:^(ALAssetsGroup *group, BOOL *stopGroups) { + [_bridge.assetsLibrary enumerateGroupsWithTypes:groupTypes usingBlock:^(ALAssetsGroup *group, BOOL *stopGroups) { if (group && (groupName == nil || [groupName isEqualToString:[group valueForProperty:ALAssetsGroupPropertyName]])) { if (assetType == nil || [assetType isEqualToString:@"Photos"]) { diff --git a/Libraries/Image/RCTImageLoader.h b/Libraries/Image/RCTImageLoader.h index 5498f23b7..f86d2a1d8 100644 --- a/Libraries/Image/RCTImageLoader.h +++ b/Libraries/Image/RCTImageLoader.h @@ -9,37 +9,31 @@ #import +#import "RCTBridge.h" + @class ALAssetsLibrary; -@class RCTBridge; typedef void (^RCTImageLoaderProgressBlock)(int64_t written, int64_t total); -typedef void (^RCTImageLoaderCompletionBlock)(NSError *error, id /* UIImage or CAAnimation */); +typedef void (^RCTImageLoaderCompletionBlock)(NSError *error, id image /* UIImage or CAAnimation */); typedef void (^RCTImageLoaderCancellationBlock)(void); -@interface RCTImageLoader : NSObject +@interface RCTImageLoader : NSObject /** - * The shared asset library instance. + * Loads the specified image at the highest available resolution. + * Can be called from any thread, will always call callback on main thread. */ -+ (ALAssetsLibrary *)assetsLibrary; - -/** - * Can be called from any thread. - * Will always call callback on main thread. - */ -+ (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag - bridge:(RCTBridge *)bridge +- (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag callback:(RCTImageLoaderCompletionBlock)callback; /** * As above, but includes target size, scale and resizeMode, which are used to * select the optimal dimensions for the loaded image. */ -+ (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag +- (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag size:(CGSize)size scale:(CGFloat)scale resizeMode:(UIViewContentMode)resizeMode - bridge:(RCTBridge *)bridge progressBlock:(RCTImageLoaderProgressBlock)progress completionBlock:(RCTImageLoaderCompletionBlock)completion; @@ -54,3 +48,17 @@ typedef void (^RCTImageLoaderCancellationBlock)(void); + (BOOL)isRemoteImage:(NSString *)imageTag; @end + +@interface RCTBridge (RCTImageLoader) + +/** + * The shared image loader instance + */ +@property (nonatomic, readonly) RCTImageLoader *imageLoader; + +/** + * The shared asset library instance. + */ +@property (nonatomic, readonly) ALAssetsLibrary *assetsLibrary; + +@end diff --git a/Libraries/Image/RCTImageLoader.m b/Libraries/Image/RCTImageLoader.m index c9aeff5fe..191472a91 100644 --- a/Libraries/Image/RCTImageLoader.m +++ b/Libraries/Image/RCTImageLoader.m @@ -48,26 +48,21 @@ static dispatch_queue_t RCTImageLoaderQueue(void) } @implementation RCTImageLoader - -+ (ALAssetsLibrary *)assetsLibrary { - static ALAssetsLibrary *assetsLibrary = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - assetsLibrary = [[ALAssetsLibrary alloc] init]; - }); - return assetsLibrary; + ALAssetsLibrary *_assetsLibrary; } -+ (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag - bridge:(RCTBridge *)bridge +@synthesize bridge = _bridge; + +RCT_EXPORT_MODULE() + +- (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag callback:(RCTImageLoaderCompletionBlock)callback { return [self loadImageWithTag:imageTag size:CGSizeZero scale:0 resizeMode:UIViewContentModeScaleToFill - bridge:bridge progressBlock:nil completionBlock:callback]; } @@ -116,11 +111,18 @@ static UIImage *RCTScaledImageForAsset(ALAssetRepresentation *representation, return nil; } -+ (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag +- (ALAssetsLibrary *)assetsLibrary +{ + if (!_assetsLibrary) { + _assetsLibrary = [[ALAssetsLibrary alloc] init]; + } + return _assetsLibrary; +} + +- (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag size:(CGSize)size scale:(CGFloat)scale resizeMode:(UIViewContentMode)resizeMode - bridge:(RCTBridge *)bridge progressBlock:(RCTImageLoaderProgressBlock)progress completionBlock:(RCTImageLoaderCompletionBlock)completion { @@ -229,7 +231,7 @@ static UIImage *RCTScaledImageForAsset(ALAssetRepresentation *representation, }]; } } else if ([imageTag hasPrefix:@"rct-image-store://"]) { - [bridge.imageStoreManager getImageForTag:imageTag withBlock:^(UIImage *image) { + [_bridge.imageStoreManager getImageForTag:imageTag withBlock:^(UIImage *image) { if (image) { RCTDispatchCallbackOnMainQueue(completion, nil, image); } else { @@ -273,3 +275,17 @@ static UIImage *RCTScaledImageForAsset(ALAssetRepresentation *representation, } @end + +@implementation RCTBridge (RCTImageLoader) + +- (RCTImageLoader *)imageLoader +{ + return self.modules[RCTBridgeModuleNameForClass([RCTImageLoader class])]; +} + +- (ALAssetsLibrary *)assetsLibrary +{ + return [self.imageLoader assetsLibrary]; +} + +@end diff --git a/Libraries/Image/RCTImageRequestHandler.m b/Libraries/Image/RCTImageRequestHandler.m index c1f485b33..595c94247 100644 --- a/Libraries/Image/RCTImageRequestHandler.m +++ b/Libraries/Image/RCTImageRequestHandler.m @@ -15,9 +15,6 @@ #import "RCTUtils.h" @implementation RCTImageRequestHandler -{ - NSInteger _currentToken; -} RCT_EXPORT_MODULE() @@ -31,9 +28,10 @@ RCT_EXPORT_MODULE() - (id)sendRequest:(NSURLRequest *)request withDelegate:(id)delegate { - NSNumber *requestToken = @(++_currentToken); NSString *URLString = [request.URL absoluteString]; - [RCTImageLoader loadImageWithTag:URLString bridge:_bridge callback:^(NSError *error, UIImage *image) { + + __block RCTImageLoaderCancellationBlock requestToken = nil; + requestToken = [_bridge.imageLoader loadImageWithTag:URLString callback:^(NSError *error, UIImage *image) { if (error) { [delegate URLRequest:requestToken didCompleteWithError:error]; return; @@ -62,4 +60,11 @@ RCT_EXPORT_MODULE() return requestToken; } +- (void)cancelRequest:(id /* RCTImageLoaderCancellationBlock */)requestToken +{ + if (requestToken) { + ((RCTImageLoaderCancellationBlock)requestToken)(); + } +} + @end diff --git a/Libraries/Image/RCTImageView.m b/Libraries/Image/RCTImageView.m index ea7b6047e..e0a26a3ce 100644 --- a/Libraries/Image/RCTImageView.m +++ b/Libraries/Image/RCTImageView.m @@ -120,13 +120,12 @@ RCT_NOT_IMPLEMENTED(-init) }; } - [RCTImageLoader loadImageWithTag:_src - size:self.bounds.size - scale:RCTScreenScale() - resizeMode:self.contentMode - bridge:_bridge - progressBlock:progressHandler - completionBlock:^(NSError *error, id image) { + [_bridge.imageLoader loadImageWithTag:_src + size:self.bounds.size + scale:RCTScreenScale() + resizeMode:self.contentMode + progressBlock:progressHandler + completionBlock:^(NSError *error, id image) { if ([image isKindOfClass:[CAAnimation class]]) { [self.layer addAnimation:image forKey:@"contents"];