diff --git a/ReactCommon/fabric/imagemanager/BUCK b/ReactCommon/fabric/imagemanager/BUCK index 79d533fcc..e2c419118 100644 --- a/ReactCommon/fabric/imagemanager/BUCK +++ b/ReactCommon/fabric/imagemanager/BUCK @@ -47,7 +47,10 @@ rn_xplat_cxx_library( ], ), fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, - fbobjc_preprocessor_flags = get_debug_preprocessor_flags() + get_apple_inspector_flags(), + fbobjc_preprocessor_flags = get_debug_preprocessor_flags() + get_apple_inspector_flags() + [ + "-DLOG_TAG=\"ReactNative\"", + "-DWITH_FBSYSTRACE=1", + ], force_static = True, ios_deps = [ "xplat//js:RCTImage", diff --git a/ReactCommon/fabric/imagemanager/platform/ios/RCTImageManager.h b/ReactCommon/fabric/imagemanager/platform/ios/RCTImageManager.h index 0bd16fdab..4e5ba6c3e 100644 --- a/ReactCommon/fabric/imagemanager/platform/ios/RCTImageManager.h +++ b/ReactCommon/fabric/imagemanager/platform/ios/RCTImageManager.h @@ -21,8 +21,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithImageLoader:(RCTImageLoader *)imageLoader; -- (facebook::react::ImageRequest)requestImage: - (const facebook::react::ImageSource &)imageSource; +- (facebook::react::ImageRequest)requestImage:(facebook::react::ImageSource)imageSource; @end diff --git a/ReactCommon/fabric/imagemanager/platform/ios/RCTImageManager.mm b/ReactCommon/fabric/imagemanager/platform/ios/RCTImageManager.mm index 5f6f3db1b..420faa24c 100644 --- a/ReactCommon/fabric/imagemanager/platform/ios/RCTImageManager.mm +++ b/ReactCommon/fabric/imagemanager/platform/ios/RCTImageManager.mm @@ -7,6 +7,9 @@ #import "RCTImageManager.h" +#import +#import + #import #import #import @@ -27,56 +30,61 @@ using namespace facebook::react; return self; } -- (ImageRequest)requestImage:(const ImageSource &)imageSource { - auto imageRequest = ImageRequest(imageSource); +- (ImageRequest)requestImage:(ImageSource)imageSource +{ + SystraceSection s("RCTImageManager::requestImage"); + auto imageRequest = ImageRequest(imageSource); auto weakObserverCoordinator = (std::weak_ptr)imageRequest.getSharedObserverCoordinator(); - NSURLRequest *request = NSURLRequestFromImageSource(imageSource); + auto sharedCancelationFunction = SharedFunction<>(); + imageRequest.setCancelationFunction(sharedCancelationFunction); - auto completionBlock = ^(NSError *error, UIImage *image) { - auto observerCoordinator = weakObserverCoordinator.lock(); - if (!observerCoordinator) { - return; - } + /* + * Even if an image is being loaded asynchronously on some other background thread, some other preparation + * work (such as creating an `NSURLRequest` object and some obscure logic inside `RCTImageLoader`) can take a couple + * of milliseconds, so we have to offload this to a separate thread. `ImageRequest` can be created as part of the + * layout process, so it must be highly performant. + */ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSURLRequest *request = NSURLRequestFromImageSource(imageSource); - if (image && !error) { - auto imageResponse = ImageResponse( - std::shared_ptr((__bridge_retained void *)image, CFRelease)); - observerCoordinator->nativeImageResponseComplete( - std::move(imageResponse)); - } else { - observerCoordinator->nativeImageResponseFailed(); - } - }; + auto completionBlock = ^(NSError *error, UIImage *image) { + auto observerCoordinator = weakObserverCoordinator.lock(); + if (!observerCoordinator) { + return; + } - auto progressBlock = ^(int64_t progress, int64_t total) { - auto observerCoordinator = weakObserverCoordinator.lock(); - if (!observerCoordinator) { - return; - } + if (image && !error) { + auto imageResponse = ImageResponse(std::shared_ptr((__bridge_retained void *)image, CFRelease)); + observerCoordinator->nativeImageResponseComplete(std::move(imageResponse)); + } else { + observerCoordinator->nativeImageResponseFailed(); + } + }; - observerCoordinator->nativeImageResponseProgress(progress / (float)total); - }; + auto progressBlock = ^(int64_t progress, int64_t total) { + auto observerCoordinator = weakObserverCoordinator.lock(); + if (!observerCoordinator) { + return; + } - RCTImageLoaderCancellationBlock cancelationBlock = - [_imageLoader loadImageWithURLRequest:request - size:CGSizeMake( - imageSource.size.width, - imageSource.size.height) - scale:imageSource.scale - clipped:YES - resizeMode:RCTResizeModeStretch - progressBlock:progressBlock - partialLoadBlock:nil - completionBlock:completionBlock]; + observerCoordinator->nativeImageResponseProgress(progress / (float)total); + }; - std::function cancelationFunction = [cancelationBlock](void) { - cancelationBlock(); - }; + RCTImageLoaderCancellationBlock cancelationBlock = + [self->_imageLoader loadImageWithURLRequest:request + size:CGSizeMake(imageSource.size.width, imageSource.size.height) + scale:imageSource.scale + clipped:YES + resizeMode:RCTResizeModeStretch + progressBlock:progressBlock + partialLoadBlock:nil + completionBlock:completionBlock]; - imageRequest.setCancelationFunction(cancelationFunction); + sharedCancelationFunction.assign([cancelationBlock]() { cancelationBlock(); }); + }); return imageRequest; }