iOS: add moduleForNameForcedLoad: to lookup modules by name and force load them

Summary:
Some module classes may not be loaded yet, so looking up via classes may not always give the correct instance. This diff added a new lookup method that delegate to the bridge delegate to force load the modules as needed.

The existing moduleForName: method was left untouched because it's solely used by RCTUIManager at the moment.

Reviewed By: dshahidehpour

Differential Revision: D13033876

fbshipit-source-id: 4082fcd68498004f678b4b95adc82b5b134fefdf
This commit is contained in:
Kevin Gozali 2018-11-13 20:09:21 -08:00 committed by Facebook Github Bot
parent 8826d8b233
commit d7a0c44590
3 changed files with 34 additions and 11 deletions

View File

@ -151,8 +151,12 @@ RCT_EXTERN void RCTEnableJSINativeModule(BOOL enabled);
* lazily instantiated, so calling these methods for the first time with a given
* module name/class may cause the class to be sychronously instantiated,
* potentially blocking both the calling thread and main thread for a short time.
*
* Note: This method does NOT lazily load the particular module if it's not yet loaded.
*/
- (id)moduleForName:(NSString *)moduleName;
- (id)moduleForName:(NSString *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad;
// Note: This method lazily load the module as necessary.
- (id)moduleForClass:(Class)moduleClass;
/**

View File

@ -241,6 +241,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
return [self.batchedBridge moduleForName:moduleName];
}
- (id)moduleForName:(NSString *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad
{
return [self.batchedBridge moduleForName:moduleName lazilyLoadIfNecessary:lazilyLoad];
}
- (id)moduleForClass:(Class)moduleClass
{
id module = [self.batchedBridge moduleForClass:moduleClass];

View File

@ -439,6 +439,30 @@ struct RCTInstanceCallback : public InstanceCallback {
return _moduleDataByName[moduleName].instance;
}
- (id)moduleForName:(NSString *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad
{
if (!lazilyLoad) {
return [self moduleForName:moduleName];
}
RCTModuleData *moduleData = _moduleDataByName[moduleName];
if (moduleData) {
return moduleData.instance;
}
// Module may not be loaded yet, so attempt to force load it here.
const BOOL result = [self.delegate respondsToSelector:@selector(bridge:didNotFindModule:)] &&
[self.delegate bridge:self didNotFindModule:moduleName];
if (result) {
// Try again.
moduleData = _moduleDataByName[moduleName];
} else {
RCTLogError(@"Unable to find module for %@", moduleName);
}
return moduleData.instance;
}
- (BOOL)moduleIsInitialized:(Class)moduleClass
{
return _moduleDataByName[RCTBridgeModuleNameForClass(moduleClass)].hasInstance;
@ -446,17 +470,7 @@ struct RCTInstanceCallback : public InstanceCallback {
- (id)moduleForClass:(Class)moduleClass
{
NSString *moduleName = RCTBridgeModuleNameForClass(moduleClass);
RCTModuleData *moduleData = _moduleDataByName[moduleName];
if (moduleData) {
return moduleData.instance;
}
// Module may not be loaded yet, so attempt to force load it here.
RCTAssert([moduleClass conformsToProtocol:@protocol(RCTBridgeModule)], @"Asking for a NativeModule that doesn't conform to RCTBridgeModule: %@", NSStringFromClass(moduleClass));
[self registerAdditionalModuleClasses:@[moduleClass]];
return _moduleDataByName[moduleName].instance;
return [self moduleForName:RCTBridgeModuleNameForClass(moduleClass) lazilyLoadIfNecessary:YES];
}
- (std::shared_ptr<ModuleRegistry>)_buildModuleRegistryUnlocked