Deprecated RCTDidCreateNativeModules notification

Summary:
public

Thanks to the new lazy initialization system for modules, `RCTDidCreateNativeModules` no longer does what the name implies.

Previously, `RCTDidCreateNativeModules` was fired after all native modules had been initialized. Now, it simply fires each time the bridge is reloaded. Modules are created on demand when they are needed, so most of the assumptions about when `RCTDidCreateNativeModules` will fire are now incorrect.

This diff deprecates `RCTDidCreateNativeModules`, and adds a new notification, `RCTDidInitializeModuleNotification`, which fires each time a module a new module is instantiated.

If you need to access a module at any time you can just call `-[bridge moduleForClass:]` and the module will be instantiated on demand. If you want to access a module *only* after it has already been instantiated, you can use the `RCTDidInitializeModuleNotification` notification.

Reviewed By: tadeuzagallo

Differential Revision: D2755036

fb-gh-sync-id: 25bab6d5eb6fcd35d43125ac45908035eea01487
This commit is contained in:
Nick Lockwood 2015-12-15 05:42:45 -08:00 committed by facebook-github-bot-5
parent 2d61dfd9c1
commit f7edcda5d7
6 changed files with 75 additions and 34 deletions

View File

@ -29,6 +29,9 @@
[[[NSThread currentThread] name] isEqualToString:@"com.facebook.React.JavaScript"], \
@"This method must be called on JS thread")
/**
* Used by RKAnalyticsCPULogger
*/
NSString *const RCTEnqueueNotification = @"RCTEnqueueNotification";
NSString *const RCTDequeueNotification = @"RCTDequeueNotification";
@ -90,9 +93,9 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
[RCTBridge setCurrentBridge:self];
[[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptWillStartLoadingNotification
object:self
userInfo:@{ @"bridge": self }];
[[NSNotificationCenter defaultCenter]
postNotificationName:RCTJavaScriptWillStartLoadingNotification
object:_parentBridge userInfo:@{@"bridge": self}];
[self start];
}
@ -208,9 +211,9 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
// Allow testing without a script
dispatch_async(dispatch_get_main_queue(), ^{
[self didFinishLoading];
[[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidLoadNotification
object:_parentBridge
userInfo:@{ @"bridge": self }];
[[NSNotificationCenter defaultCenter]
postNotificationName:RCTJavaScriptDidLoadNotification
object:_parentBridge userInfo:@{@"bridge": self}];
});
onSourceLoad(nil, nil);
}
@ -331,8 +334,15 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
}
}
[[NSNotificationCenter defaultCenter] postNotificationName:RCTDidCreateNativeModules
object:self];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[[NSNotificationCenter defaultCenter]
postNotificationName:RCTDidCreateNativeModules
object:self userInfo:@{@"bridge": self}];
#pragma clang diagnostic pop
RCTPerformanceLoggerEnd(RCTPLNativeModuleInit);
}
@ -429,10 +439,9 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
// timing issues with RCTRootView
dispatch_async(dispatch_get_main_queue(), ^{
[self didFinishLoading];
[[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidLoadNotification
object:_parentBridge
userInfo:@{ @"bridge": self }];
[[NSNotificationCenter defaultCenter]
postNotificationName:RCTJavaScriptDidLoadNotification
object:_parentBridge userInfo:@{@"bridge": self}];
});
}];
}
@ -457,9 +466,10 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
_loading = NO;
[[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidFailToLoadNotification
object:_parentBridge
userInfo:@{@"bridge": self, @"error": error}];
[[NSNotificationCenter defaultCenter]
postNotificationName:RCTJavaScriptDidFailToLoadNotification
object:_parentBridge userInfo:@{@"bridge": self, @"error": error}];
RCTFatal(error);
}
@ -715,7 +725,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
{
RCTAssertJSThread();
[[NSNotificationCenter defaultCenter] postNotificationName:RCTEnqueueNotification object:nil userInfo:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:RCTEnqueueNotification object:self userInfo:nil];
RCTJavaScriptCallback processResponse = ^(id json, NSError *error) {
if (error) {
@ -725,7 +735,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
if (!self.isValid) {
return;
}
[[NSNotificationCenter defaultCenter] postNotificationName:RCTDequeueNotification object:nil userInfo:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:RCTDequeueNotification object:self userInfo:nil];
[self handleBuffer:json batchEnded:YES];
};
@ -740,7 +750,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
{
RCTAssertJSThread();
[[NSNotificationCenter defaultCenter] postNotificationName:RCTEnqueueNotification object:nil userInfo:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:RCTEnqueueNotification object:self userInfo:nil];
RCTJavaScriptCallback processResponse = ^(id json, NSError *error) {
if (error) {
@ -750,7 +760,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
if (!self.isValid) {
return;
}
[[NSNotificationCenter defaultCenter] postNotificationName:RCTDequeueNotification object:nil userInfo:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:RCTDequeueNotification object:self userInfo:nil];
[self handleBuffer:json batchEnded:YES];
};

View File

@ -25,24 +25,28 @@
RCT_EXTERN NSString *const RCTReloadNotification;
/**
* This notification fires when the bridge starts loading.
* This notification fires when the bridge starts loading the JS bundle.
*/
RCT_EXTERN NSString *const RCTJavaScriptWillStartLoadingNotification;
/**
* This notification fires when the bridge has finished loading.
* This notification fires when the bridge has finished loading the JS bundle.
*/
RCT_EXTERN NSString *const RCTJavaScriptDidLoadNotification;
/**
* This notification fires when the bridge failed to load.
* This notification fires when the bridge failed to load the JS bundle. The
* `error` key can be used to determine the error that occured.
*/
RCT_EXTERN NSString *const RCTJavaScriptDidFailToLoadNotification;
/**
* This notification fires when the bridge created all registered native modules
* This notification fires each time a native module is instantiated. The
* `module` key will contain a reference to the newly-created module instance.
* Note that this notification may be fired before the module is available via
* the `[bridge moduleForClass:]` method.
*/
RCT_EXTERN NSString *const RCTDidCreateNativeModules;
RCT_EXTERN NSString *const RCTDidInitializeModuleNotification;
/**
* This block can be used to instantiate modules that require additional
@ -171,10 +175,28 @@ RCT_EXTERN BOOL RCTBridgeModuleClassIsRegistered(Class);
@end
/**
* These properties and methods are deprecated and should not be used
* These features are deprecated and should not be used.
*/
@interface RCTBridge (Deprecated)
/**
* This notification used to fire after all native modules has been initialized,
* but now that native modules are instantiated lazily on demand, its original
* purpose is meaningless.
*
* If you need to access a module, you can do so as soon as the bridge has been
* initialized, by calling `[bridge moduleForClass:]`. If you need to know when
* an individual module has been instantiated, use the `RCTDidInitializeModule`
* notification instead.
*/
RCT_EXTERN NSString *const RCTDidCreateNativeModules
__deprecated_msg("Use RCTDidInitializeModule to observe init of individual modules");
/**
* Accessing the modules property causes all modules to be eagerly initialized,
* which stalls the main thread. Use moduleClasses to enumerate through modules
* without causing them to be instantiated.
*/
@property (nonatomic, copy, readonly) NSDictionary *modules
__deprecated_msg("Use moduleClasses and/or moduleForName: instead");

View File

@ -22,7 +22,7 @@ NSString *const RCTReloadNotification = @"RCTReloadNotification";
NSString *const RCTJavaScriptWillStartLoadingNotification = @"RCTJavaScriptWillStartLoadingNotification";
NSString *const RCTJavaScriptDidLoadNotification = @"RCTJavaScriptDidLoadNotification";
NSString *const RCTJavaScriptDidFailToLoadNotification = @"RCTJavaScriptDidFailToLoadNotification";
NSString *const RCTDidCreateNativeModules = @"RCTDidCreateNativeModules";
NSString *const RCTDidInitializeModuleNotification = @"RCTDidInitializeModuleNotification";
@interface RCTBatchedBridge : RCTBridge <RCTInvalidating>
@ -213,10 +213,10 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
[commands registerKeyCommandWithInput:@"r"
modifierFlags:UIKeyModifierCommand
action:^(__unused UIKeyCommand *command) {
[[NSNotificationCenter defaultCenter] postNotificationName:RCTReloadNotification
object:nil
userInfo:nil];
}];
[[NSNotificationCenter defaultCenter] postNotificationName:RCTReloadNotification
object:nil
userInfo:nil];
}];
#endif
}
@ -305,6 +305,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
@implementation RCTBridge(Deprecated)
NSString *const RCTDidCreateNativeModules = @"RCTDidCreateNativeModules";
- (NSDictionary *)modules
{
return self.batchedBridge.modules;

View File

@ -79,6 +79,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
- (void)setBridgeForInstance:(RCTBridge *)bridge
{
_bridge = bridge;
if ([_instance respondsToSelector:@selector(bridge)]) {
@try {
[(id)_instance setValue:bridge forKey:@"bridge"];
@ -198,6 +199,12 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
}
}
}
// Needs to be sent after bridge has been set for all module instances.
// Makes sense to put it here, since the same rules apply for methodQueue.
[[NSNotificationCenter defaultCenter]
postNotificationName:RCTDidInitializeModuleNotification
object:_bridge userInfo:@{@"module": _instance}];
}
return _methodQueue;
}

View File

@ -347,7 +347,7 @@ extern NSString *RCTBridgeModuleNameForClass(Class cls);
[[NSNotificationCenter defaultCenter] postNotificationName:RCTUIManagerDidRegisterRootViewNotification
object:self
userInfo:@{ RCTUIManagerRootViewKey: rootView }];
userInfo:@{RCTUIManagerRootViewKey: rootView}];
}
- (UIView *)viewForReactTag:(NSNumber *)reactTag
@ -695,7 +695,7 @@ RCT_EXPORT_METHOD(removeRootView:(nonnull NSNumber *)rootReactTag)
[[NSNotificationCenter defaultCenter] postNotificationName:RCTUIManagerDidRemoveRootViewNotification
object:uiManager
userInfo:@{ RCTUIManagerRootViewKey: rootView }];
userInfo:@{RCTUIManagerRootViewKey: rootView}];
}];
}

View File

@ -403,7 +403,7 @@ void RCTProfileInit(RCTBridge *bridge)
forMode:NSRunLoopCommonModes];
[[NSNotificationCenter defaultCenter] postNotificationName:RCTProfileDidStartProfiling
object:nil];
object:bridge];
}
void RCTProfileEnd(RCTBridge *bridge, void (^callback)(NSString *))
@ -417,7 +417,7 @@ void RCTProfileEnd(RCTBridge *bridge, void (^callback)(NSString *))
OSAtomicAnd32Barrier(0, &RCTProfileProfiling);
[[NSNotificationCenter defaultCenter] postNotificationName:RCTProfileDidEndProfiling
object:nil];
object:bridge];
[RCTProfileDisplayLink invalidate];
RCTProfileDisplayLink = nil;