From ea069b69de427832226c4fe6e32803b4c7c31d2c Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Fri, 17 Mar 2017 06:55:43 -0700 Subject: [PATCH] Make Cxx modules lazy on iOS Reviewed By: mhorowitz Differential Revision: D4716040 fbshipit-source-id: 08cc1317e15f0b3bd1df6d76c483a560f5c43d53 --- React/CxxBridge/RCTCxxBridge.mm | 2 +- React/CxxModule/RCTCxxModule.h | 15 ++++----- React/CxxModule/RCTCxxModule.mm | 56 +++++++++++++++++---------------- 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm index 9eeceb387..a98b0e2a9 100644 --- a/React/CxxBridge/RCTCxxBridge.mm +++ b/React/CxxBridge/RCTCxxBridge.mm @@ -505,7 +505,7 @@ struct RCTInstanceCallback : public InstanceCallback { modules.emplace_back(std::make_unique( _reactInstance, [moduleData.name UTF8String], - [moduleData] { return [(RCTCxxModule *)(moduleData.instance) move]; }, + [moduleData] { return [(RCTCxxModule *)(moduleData.instance) createModule]; }, std::make_shared(moduleData))); } else { modules.emplace_back(std::make_unique(self, moduleData)); diff --git a/React/CxxModule/RCTCxxModule.h b/React/CxxModule/RCTCxxModule.h index b95889df7..0f08f3113 100644 --- a/React/CxxModule/RCTCxxModule.h +++ b/React/CxxModule/RCTCxxModule.h @@ -14,14 +14,15 @@ #import #import +/** + * Subclass RCTCxxModule to use cross-platform CxxModule on iOS. + * + * Subclasses must implement the createModule method to lazily produce the module. When running under the Cxx bridge + * modules will be accessed directly, under the Objective-C bridge method access is wrapped through RCTCxxMethod. + */ @interface RCTCxxModule : NSObject -- (instancetype)initWithCxxModule:(std::unique_ptr)module; - -- (NSArray *)methodsToExport; -- (NSDictionary *)constantsToExport; - -// Extracts the module from its objc wrapper -- (std::unique_ptr)move; +// To be implemented by subclasses +- (std::unique_ptr)createModule; @end diff --git a/React/CxxModule/RCTCxxModule.mm b/React/CxxModule/RCTCxxModule.mm index a2be24170..3838cb7bc 100644 --- a/React/CxxModule/RCTCxxModule.mm +++ b/React/CxxModule/RCTCxxModule.mm @@ -23,37 +23,36 @@ using namespace facebook::react; std::unique_ptr _module; } -- (instancetype)init -{ - return nil; -} - -- (instancetype)initWithCxxModule:(std::unique_ptr)module -{ - RCTAssert([RCTBridgeModuleNameForClass([self class]) isEqualToString:@(module->getName().c_str())], - @"CxxModule class name %@ does not match runtime name %s", - RCTBridgeModuleNameForClass([self class]), module->getName().c_str()); - - if ((self = [super init])) { - _module = std::move(module); - } - - return self; -} - -- (std::unique_ptr)move -{ - return std::move(_module); -} - + (NSString *)moduleName { return @""; } -- (NSArray *)methodsToExport +- (void)lazyInit { - CHECK(_module) << "Can't call methodsToExport on moved module"; + if (!_module) { + _module = [self createModule]; + + if (_module) { + RCTAssert([RCTBridgeModuleNameForClass([self class]) isEqualToString:@(_module->getName().c_str())], + @"CxxModule class name %@ does not match runtime name %s", + RCTBridgeModuleNameForClass([self class]), _module->getName().c_str()); + } + } +} + +- (std::unique_ptr)createModule +{ + RCTAssert(NO, @"Subclass %@ must override createModule", [self class]); + return nullptr; +} + +- (NSArray> *)methodsToExport; +{ + [self lazyInit]; + if (!_module) { + return nil; + } NSMutableArray *moduleMethods = [NSMutableArray new]; for (const auto &method : _module->getMethods()) { @@ -62,9 +61,12 @@ using namespace facebook::react; return moduleMethods; } -- (NSDictionary *)constantsToExport +- (NSDictionary *)constantsToExport; { - CHECK(_module) << "Can't call constantsToExport on moved module"; + [self lazyInit]; + if (!_module) { + return nil; + } NSMutableDictionary *moduleConstants = [NSMutableDictionary new]; for (const auto &c : _module->getConstants()) {