[ReactNative] Fix RootContentView release when the top-level bridge is held

Summary:
The RCTRootView creates a underlying RCTRootContentView that was deallocated when
the bridge modules were deallocated. That doesn't work when the bridge is held.

@public

Test Plan:
Launch Groups, put a breakpoint on `-[RCTRootContentView dealloc]`, enter and
leave a group page. It should be called now.
This commit is contained in:
Tadeu Zagallo 2015-05-12 07:44:38 -07:00 committed by Christopher Chedeau
parent a142ed50ff
commit 92d7324f15
3 changed files with 18 additions and 12 deletions

View File

@ -873,15 +873,19 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
return _eventDispatcher ?: _batchedBridge.eventDispatcher; return _eventDispatcher ?: _batchedBridge.eventDispatcher;
} }
#define RCT_BRIDGE_WARN(...) \ #define RCT_INNER_BRIDGE_ONLY(...) \
- (void)__VA_ARGS__ \ - (void)__VA_ARGS__ \
{ \ { \
RCTLogMustFix(@"Called method \"%@\" on top level bridge. This method should \ RCTLogMustFix(@"Called method \"%@\" on top level bridge. This method should \
only be called from bridge instance in a bridge module", @(__func__)); \ only be called from bridge instance in a bridge module", @(__func__)); \
} }
RCT_BRIDGE_WARN(enqueueJSCall:(NSString *)moduleDotMethod args:(NSArray *)args) - (void)enqueueJSCall:(NSString *)moduleDotMethod args:(NSArray *)args
RCT_BRIDGE_WARN(_invokeAndProcessModule:(NSString *)module method:(NSString *)method arguments:(NSArray *)args context:(NSNumber *)context) {
[self.batchedBridge enqueueJSCall:moduleDotMethod args:args];
}
RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSString *)method arguments:(NSArray *)args context:(NSNumber *)context)
@end @end
@ -1499,6 +1503,7 @@ RCT_BRIDGE_WARN(_invokeAndProcessModule:(NSString *)module method:(NSString *)me
@"module": method.moduleClassName, @"module": method.moduleClassName,
@"method": method.JSMethodName, @"method": method.JSMethodName,
@"selector": NSStringFromSelector(method.selector), @"selector": NSStringFromSelector(method.selector),
@"args": RCTJSONStringify(params ?: [NSNull null], NULL),
}); });
} forModule:@(moduleID)]; } forModule:@(moduleID)];

View File

@ -11,6 +11,7 @@
#import <objc/runtime.h> #import <objc/runtime.h>
#import "RCTAssert.h"
#import "RCTBridge.h" #import "RCTBridge.h"
#import "RCTContextExecutor.h" #import "RCTContextExecutor.h"
#import "RCTEventDispatcher.h" #import "RCTEventDispatcher.h"
@ -53,6 +54,7 @@
- (instancetype)initWithBridge:(RCTBridge *)bridge - (instancetype)initWithBridge:(RCTBridge *)bridge
moduleName:(NSString *)moduleName moduleName:(NSString *)moduleName
{ {
RCTAssertMainThread();
RCTAssert(bridge, @"A bridge instance is required to create an RCTRootView"); RCTAssert(bridge, @"A bridge instance is required to create an RCTRootView");
RCTAssert(moduleName, @"A moduleName is required to create an RCTRootView"); RCTAssert(moduleName, @"A moduleName is required to create an RCTRootView");
@ -150,7 +152,7 @@ RCT_IMPORT_METHOD(ReactNative, unmountComponentAtNodeAndRemoveContainer)
- (void)dealloc - (void)dealloc
{ {
[[NSNotificationCenter defaultCenter] removeObserver:self]; [[NSNotificationCenter defaultCenter] removeObserver:self];
[_contentView removeFromSuperview]; [_contentView invalidate];
} }
@end @end
@ -212,13 +214,12 @@ RCT_IMPORT_METHOD(ReactNative, unmountComponentAtNodeAndRemoveContainer)
- (void)invalidate - (void)invalidate
{ {
if (self.isValid) {
self.userInteractionEnabled = NO; self.userInteractionEnabled = NO;
} [self removeFromSuperview];
- (void)dealloc
{
[_bridge enqueueJSCall:@"ReactNative.unmountComponentAtNodeAndRemoveContainer" [_bridge enqueueJSCall:@"ReactNative.unmountComponentAtNodeAndRemoveContainer"
args:@[self.reactTag]]; args:@[self.reactTag]];
}
} }
@end @end

View File

@ -281,7 +281,7 @@ static NSDictionary *RCTViewConfigForModule(Class managerClass, NSString *viewNa
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
for (NSNumber *rootViewTag in _rootViewTags) { for (NSNumber *rootViewTag in _rootViewTags) {
((UIView *)_viewRegistry[rootViewTag]).userInteractionEnabled = NO; [_viewRegistry[rootViewTag] invalidate];
} }
_rootViewTags = nil; _rootViewTags = nil;