iOS: Introduced RCTImageURLLoaderWithAttribution

Summary:
Changelog: [iOS] [Changed] - New internal image attribution support, but files importing RCTImageLoader.h must be converted to ObjC++

This new interface is the same as RCTImageURLLoader, but with additional support to pass in optional attribution information. The attribution info is not strictly defined (we may do so in the future though), and it's up to the hosting application and RCTImageURLLoader classes to handle it.

Reviewed By: sammy-SC

Differential Revision: D18492882

fbshipit-source-id: c3870c60e6c2e7c65758fc3235ebf5db369e07dc
This commit is contained in:
Kevin Gozali 2019-11-16 00:10:25 -08:00 коммит произвёл Facebook Github Bot
Родитель 806a2b8103
Коммит fdcdca4cfa
6 изменённых файлов: 136 добавлений и 11 удалений

Просмотреть файл

@ -15,6 +15,7 @@
#import <React/RCTDefines.h>
#import <React/RCTImageCache.h>
#import <React/RCTImageLoader.h>
#import <React/RCTImageLoaderWithAttributionProtocol.h>
#import <React/RCTImageUtils.h>
#import <React/RCTLog.h>
#import <React/RCTNetworking.h>
@ -22,13 +23,15 @@
#import "RCTImagePlugins.h"
using namespace facebook::react;
static NSInteger RCTImageBytesForImage(UIImage *image)
{
NSInteger singleImageBytes = image.size.width * image.size.height * image.scale * image.scale * 4;
return image.images ? image.images.count * singleImageBytes : singleImageBytes;
}
@interface RCTImageLoader() <NativeImageLoaderIOSSpec>
@interface RCTImageLoader() <NativeImageLoaderIOSSpec, RCTImageLoaderWithAttributionProtocol>
@end
@ -288,11 +291,32 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image,
scale:1
clipped:YES
resizeMode:RCTResizeModeStretch
attribution:{}
progressBlock:nil
partialLoadBlock:nil
completionBlock:callback];
}
- (RCTImageLoaderCancellationBlock)loadImageWithURLRequest:(NSURLRequest *)imageURLRequest
size:(CGSize)size
scale:(CGFloat)scale
clipped:(BOOL)clipped
resizeMode:(RCTResizeMode)resizeMode
progressBlock:(RCTImageLoaderProgressBlock)progressBlock
partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadBlock
completionBlock:(RCTImageLoaderCompletionBlock)completionBlock
{
return [self loadImageWithURLRequest:imageURLRequest
size:size
scale:scale
clipped:clipped
resizeMode:resizeMode
attribution:{}
progressBlock:progressBlock
partialLoadBlock:partialLoadBlock
completionBlock:completionBlock];
}
- (void)dequeueTasks
{
dispatch_async(_URLRequestQueue, ^{
@ -363,6 +387,7 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image,
size:(CGSize)size
scale:(CGFloat)scale
resizeMode:(RCTResizeMode)resizeMode
attribution:(const ImageURLLoaderAttribution &)attribution
progressBlock:(RCTImageLoaderProgressBlock)progressHandler
partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadHandler
completionBlock:(void (^)(NSError *error, id imageOrData, BOOL cacheResult, NSURLResponse *response))completionBlock
@ -383,6 +408,9 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image,
request = mutableRequest;
}
// Create a copy here so the value is retained when accessed in the blocks below.
ImageURLLoaderAttribution attributionCopy(attribution);
// Find suitable image URL loader
id<RCTImageURLLoader> loadHandler = [self imageURLLoaderForURL:request.URL];
BOOL requiresScheduling = [loadHandler respondsToSelector:@selector(requiresScheduling)] ?
@ -417,13 +445,25 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image,
// If the loader doesn't require scheduling we call it directly on
// the main queue.
if (loadHandler && !requiresScheduling) {
if ([loadHandler conformsToProtocol:@protocol(RCTImageURLLoaderWithAttribution)]) {
return [(id<RCTImageURLLoaderWithAttribution>)loadHandler loadImageForURL:request.URL
size:size
scale:scale
resizeMode:resizeMode
attribution:attributionCopy
progressHandler:progressHandler
partialLoadHandler:partialLoadHandler
completionHandler:^(NSError *error, UIImage *image) {
completionHandler(error, image, nil);
}];
}
return [loadHandler loadImageForURL:request.URL
size:size
scale:scale
resizeMode:resizeMode
progressHandler:progressHandler
partialLoadHandler:partialLoadHandler
completionHandler:^(NSError *error, UIImage *image){
completionHandler:^(NSError *error, UIImage *image) {
completionHandler(error, image, nil);
}];
}
@ -441,15 +481,29 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image,
}
if (loadHandler) {
dispatch_block_t cancelLoadLocal = [loadHandler loadImageForURL:request.URL
size:size
scale:scale
resizeMode:resizeMode
progressHandler:progressHandler
partialLoadHandler:partialLoadHandler
completionHandler:^(NSError *error, UIImage *image) {
completionHandler(error, image, nil);
}];
dispatch_block_t cancelLoadLocal;
if ([loadHandler conformsToProtocol:@protocol(RCTImageURLLoaderWithAttribution)]) {
cancelLoadLocal = [(id<RCTImageURLLoaderWithAttribution>)loadHandler loadImageForURL:request.URL
size:size
scale:scale
resizeMode:resizeMode
attribution:attributionCopy
progressHandler:progressHandler
partialLoadHandler:partialLoadHandler
completionHandler:^(NSError *error, UIImage *image) {
completionHandler(error, image, nil);
}];
} else {
cancelLoadLocal = [loadHandler loadImageForURL:request.URL
size:size
scale:scale
resizeMode:resizeMode
progressHandler:progressHandler
partialLoadHandler:partialLoadHandler
completionHandler:^(NSError *error, UIImage *image) {
completionHandler(error, image, nil);
}];
}
[cancelLoadLock lock];
cancelLoad = cancelLoadLocal;
[cancelLoadLock unlock];
@ -607,6 +661,7 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image,
scale:(CGFloat)scale
clipped:(BOOL)clipped
resizeMode:(RCTResizeMode)resizeMode
attribution:(const ImageURLLoaderAttribution &)attribution
progressBlock:(RCTImageLoaderProgressBlock)progressBlock
partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadBlock
completionBlock:(RCTImageLoaderCompletionBlock)completionBlock
@ -673,6 +728,7 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image,
size:size
scale:scale
resizeMode:resizeMode
attribution:attribution
progressBlock:progressBlock
partialLoadBlock:partialLoadBlock
completionBlock:completionHandler];
@ -830,6 +886,7 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image,
size:CGSizeZero
scale:1
resizeMode:RCTResizeModeStretch
attribution:{}
progressBlock:NULL
partialLoadBlock:NULL
completionBlock:completion];

Просмотреть файл

@ -113,4 +113,5 @@
* protocol. This method should be called in bridgeDidInitializeModule.
*/
- (void)setImageCache:(id<RCTImageCache>)cache;
@end

Просмотреть файл

@ -0,0 +1,29 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <UIKit/UIKit.h>
#import <React/RCTImageLoaderProtocol.h>
#import <React/RCTImageURLLoaderWithAttribution.h>
@protocol RCTImageLoaderWithAttributionProtocol<RCTImageLoaderProtocol>
/**
* Same as the variant in RCTImageURLLoaderProtocol, but allows passing attribution
* information that each image URL loader can process.
*/
- (RCTImageLoaderCancellationBlock)loadImageWithURLRequest:(NSURLRequest *)imageURLRequest
size:(CGSize)size
scale:(CGFloat)scale
clipped:(BOOL)clipped
resizeMode:(RCTResizeMode)resizeMode
attribution:(const facebook::react::ImageURLLoaderAttribution &)attribution
progressBlock:(RCTImageLoaderProgressBlock)progressBlock
partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadBlock
completionBlock:(RCTImageLoaderCompletionBlock)completionBlock;
@end

Просмотреть файл

@ -0,0 +1,38 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/RCTImageURLLoader.h>
namespace facebook {
namespace react {
struct ImageURLLoaderAttribution {
int32_t surfaceId = 0;
};
} // namespace react
} // namespace facebook
/**
* Same as the RCTImageURLLoader interface, but allows passing in optional `attribution` information.
* This is useful for per-app logging and other instrumentation.
*/
@protocol RCTImageURLLoaderWithAttribution <RCTImageURLLoader>
/**
* Same as the RCTImageURLLoader variant above, but allows optional `attribution` information.
*/
- (RCTImageLoaderCancellationBlock)loadImageForURL:(NSURL *)imageURL
size:(CGSize)size
scale:(CGFloat)scale
resizeMode:(RCTResizeMode)resizeMode
attribution:(const facebook::react::ImageURLLoaderAttribution &)attribution
progressHandler:(RCTImageLoaderProgressBlock)progressHandler
partialLoadHandler:(RCTImageLoaderPartialLoadBlock)partialLoadHandler
completionHandler:(RCTImageLoaderCompletionBlock)completionHandler;
@end

Просмотреть файл