Converted RCTImageLoader to be a bridge module

This commit is contained in:
Nick Lockwood 2015-07-27 08:48:31 -07:00
parent d178e27939
commit 2c5290946b
5 changed files with 71 additions and 43 deletions

View File

@ -29,12 +29,12 @@ RCT_EXPORT_METHOD(saveImageWithTag:(NSString *)imageTag
successCallback:(RCTResponseSenderBlock)successCallback successCallback:(RCTResponseSenderBlock)successCallback
errorCallback:(RCTResponseErrorBlock)errorCallback) errorCallback:(RCTResponseErrorBlock)errorCallback)
{ {
[RCTImageLoader loadImageWithTag:imageTag bridge:_bridge callback:^(NSError *loadError, UIImage *loadedImage) { [_bridge.imageLoader loadImageWithTag:imageTag callback:^(NSError *loadError, UIImage *loadedImage) {
if (loadError) { if (loadError) {
errorCallback(loadError); errorCallback(loadError);
return; 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) { if (saveError) {
RCTLogWarn(@"Error saving cropped image: %@", saveError); RCTLogWarn(@"Error saving cropped image: %@", saveError);
errorCallback(saveError); errorCallback(saveError);
@ -96,7 +96,7 @@ RCT_EXPORT_METHOD(getPhotos:(NSDictionary *)params
BOOL __block calledCallback = NO; BOOL __block calledCallback = NO;
NSMutableArray *assets = [[NSMutableArray alloc] init]; 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 (group && (groupName == nil || [groupName isEqualToString:[group valueForProperty:ALAssetsGroupPropertyName]])) {
if (assetType == nil || [assetType isEqualToString:@"Photos"]) { if (assetType == nil || [assetType isEqualToString:@"Photos"]) {

View File

@ -9,37 +9,31 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import "RCTBridge.h"
@class ALAssetsLibrary; @class ALAssetsLibrary;
@class RCTBridge;
typedef void (^RCTImageLoaderProgressBlock)(int64_t written, int64_t total); 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); typedef void (^RCTImageLoaderCancellationBlock)(void);
@interface RCTImageLoader : NSObject @interface RCTImageLoader : NSObject <RCTBridgeModule>
/** /**
* 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; - (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag
/**
* Can be called from any thread.
* Will always call callback on main thread.
*/
+ (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag
bridge:(RCTBridge *)bridge
callback:(RCTImageLoaderCompletionBlock)callback; callback:(RCTImageLoaderCompletionBlock)callback;
/** /**
* As above, but includes target size, scale and resizeMode, which are used to * As above, but includes target size, scale and resizeMode, which are used to
* select the optimal dimensions for the loaded image. * select the optimal dimensions for the loaded image.
*/ */
+ (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag - (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag
size:(CGSize)size size:(CGSize)size
scale:(CGFloat)scale scale:(CGFloat)scale
resizeMode:(UIViewContentMode)resizeMode resizeMode:(UIViewContentMode)resizeMode
bridge:(RCTBridge *)bridge
progressBlock:(RCTImageLoaderProgressBlock)progress progressBlock:(RCTImageLoaderProgressBlock)progress
completionBlock:(RCTImageLoaderCompletionBlock)completion; completionBlock:(RCTImageLoaderCompletionBlock)completion;
@ -54,3 +48,17 @@ typedef void (^RCTImageLoaderCancellationBlock)(void);
+ (BOOL)isRemoteImage:(NSString *)imageTag; + (BOOL)isRemoteImage:(NSString *)imageTag;
@end @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

View File

@ -48,26 +48,21 @@ static dispatch_queue_t RCTImageLoaderQueue(void)
} }
@implementation RCTImageLoader @implementation RCTImageLoader
+ (ALAssetsLibrary *)assetsLibrary
{ {
static ALAssetsLibrary *assetsLibrary = nil; ALAssetsLibrary *_assetsLibrary;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
assetsLibrary = [[ALAssetsLibrary alloc] init];
});
return assetsLibrary;
} }
+ (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag @synthesize bridge = _bridge;
bridge:(RCTBridge *)bridge
RCT_EXPORT_MODULE()
- (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag
callback:(RCTImageLoaderCompletionBlock)callback callback:(RCTImageLoaderCompletionBlock)callback
{ {
return [self loadImageWithTag:imageTag return [self loadImageWithTag:imageTag
size:CGSizeZero size:CGSizeZero
scale:0 scale:0
resizeMode:UIViewContentModeScaleToFill resizeMode:UIViewContentModeScaleToFill
bridge:bridge
progressBlock:nil progressBlock:nil
completionBlock:callback]; completionBlock:callback];
} }
@ -116,11 +111,18 @@ static UIImage *RCTScaledImageForAsset(ALAssetRepresentation *representation,
return nil; return nil;
} }
+ (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag - (ALAssetsLibrary *)assetsLibrary
{
if (!_assetsLibrary) {
_assetsLibrary = [[ALAssetsLibrary alloc] init];
}
return _assetsLibrary;
}
- (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag
size:(CGSize)size size:(CGSize)size
scale:(CGFloat)scale scale:(CGFloat)scale
resizeMode:(UIViewContentMode)resizeMode resizeMode:(UIViewContentMode)resizeMode
bridge:(RCTBridge *)bridge
progressBlock:(RCTImageLoaderProgressBlock)progress progressBlock:(RCTImageLoaderProgressBlock)progress
completionBlock:(RCTImageLoaderCompletionBlock)completion completionBlock:(RCTImageLoaderCompletionBlock)completion
{ {
@ -229,7 +231,7 @@ static UIImage *RCTScaledImageForAsset(ALAssetRepresentation *representation,
}]; }];
} }
} else if ([imageTag hasPrefix:@"rct-image-store://"]) { } else if ([imageTag hasPrefix:@"rct-image-store://"]) {
[bridge.imageStoreManager getImageForTag:imageTag withBlock:^(UIImage *image) { [_bridge.imageStoreManager getImageForTag:imageTag withBlock:^(UIImage *image) {
if (image) { if (image) {
RCTDispatchCallbackOnMainQueue(completion, nil, image); RCTDispatchCallbackOnMainQueue(completion, nil, image);
} else { } else {
@ -273,3 +275,17 @@ static UIImage *RCTScaledImageForAsset(ALAssetRepresentation *representation,
} }
@end @end
@implementation RCTBridge (RCTImageLoader)
- (RCTImageLoader *)imageLoader
{
return self.modules[RCTBridgeModuleNameForClass([RCTImageLoader class])];
}
- (ALAssetsLibrary *)assetsLibrary
{
return [self.imageLoader assetsLibrary];
}
@end

View File

@ -15,9 +15,6 @@
#import "RCTUtils.h" #import "RCTUtils.h"
@implementation RCTImageRequestHandler @implementation RCTImageRequestHandler
{
NSInteger _currentToken;
}
RCT_EXPORT_MODULE() RCT_EXPORT_MODULE()
@ -31,9 +28,10 @@ RCT_EXPORT_MODULE()
- (id)sendRequest:(NSURLRequest *)request - (id)sendRequest:(NSURLRequest *)request
withDelegate:(id<RCTURLRequestDelegate>)delegate withDelegate:(id<RCTURLRequestDelegate>)delegate
{ {
NSNumber *requestToken = @(++_currentToken);
NSString *URLString = [request.URL absoluteString]; 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) { if (error) {
[delegate URLRequest:requestToken didCompleteWithError:error]; [delegate URLRequest:requestToken didCompleteWithError:error];
return; return;
@ -62,4 +60,11 @@ RCT_EXPORT_MODULE()
return requestToken; return requestToken;
} }
- (void)cancelRequest:(id /* RCTImageLoaderCancellationBlock */)requestToken
{
if (requestToken) {
((RCTImageLoaderCancellationBlock)requestToken)();
}
}
@end @end

View File

@ -120,13 +120,12 @@ RCT_NOT_IMPLEMENTED(-init)
}; };
} }
[RCTImageLoader loadImageWithTag:_src [_bridge.imageLoader loadImageWithTag:_src
size:self.bounds.size size:self.bounds.size
scale:RCTScreenScale() scale:RCTScreenScale()
resizeMode:self.contentMode resizeMode:self.contentMode
bridge:_bridge progressBlock:progressHandler
progressBlock:progressHandler completionBlock:^(NSError *error, id image) {
completionBlock:^(NSError *error, id image) {
if ([image isKindOfClass:[CAAnimation class]]) { if ([image isKindOfClass:[CAAnimation class]]) {
[self.layer addAnimation:image forKey:@"contents"]; [self.layer addAnimation:image forKey:@"contents"];