New UIManager API allowing intercept/delay mounting process

Summary: In some embedding/interop cases (RN inside, something else outside), the interop layer has to have the ability to control (intercept, delay, perform synchronously with another stuff) mounting process. This API allows doing that.

Reviewed By: fkgozali

Differential Revision: D7014179

fbshipit-source-id: 04036095f7e60a5ff7e69025ff6066fea92eb361
This commit is contained in:
Valentin Shergin 2018-02-20 22:11:55 -08:00 committed by Facebook Github Bot
parent 60c000022e
commit 402ae2f01f
3 changed files with 46 additions and 8 deletions

View File

@ -1081,6 +1081,26 @@ RCT_EXPORT_METHOD(dispatchViewManagerCommand:(nonnull NSNumber *)reactTag
return;
}
__weak typeof(self) weakSelf = self;
void (^mountingBlock)(void) = ^{
typeof(self) strongSelf = weakSelf;
@try {
for (RCTViewManagerUIBlock block in previousPendingUIBlocks) {
block(strongSelf, strongSelf->_viewRegistry);
}
}
@catch (NSException *exception) {
RCTLogError(@"Exception thrown while executing UI block: %@", exception);
}
};
if ([self.observerCoordinator uiManager:self performMountingWithBlock:mountingBlock]) {
completion();
return;
}
// Execute the previously queued UI blocks
RCTProfileBeginFlowEvent();
RCTExecuteOnMainQueue(^{
@ -1088,14 +1108,9 @@ RCT_EXPORT_METHOD(dispatchViewManagerCommand:(nonnull NSNumber *)reactTag
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"-[UIManager flushUIBlocks]", (@{
@"count": [@(previousPendingUIBlocks.count) stringValue],
}));
@try {
for (RCTViewManagerUIBlock block in previousPendingUIBlocks) {
block(self, self->_viewRegistry);
}
}
@catch (NSException *exception) {
RCTLogError(@"Exception thrown while executing UI block: %@", exception);
}
mountingBlock();
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"");
RCTExecuteOnUIManagerQueue(completion);

View File

@ -9,6 +9,8 @@
#import <React/RCTViewManager.h>
typedef dispatch_block_t RCTUIManagerMountingBlock;
/**
* Allows hooking into UIManager internals. This can be used to execute code at
* specific points during the view updating process.
@ -43,6 +45,13 @@
*/
- (void)uiManagerWillPerformMounting:(RCTUIManager *)manager;
/**
* Called right before flushing UI blocks and allows to intercept the mounting process.
* Return `YES` to cancel default execution of the `block` (and perform the
* execution later).
*/
- (BOOL)uiManager:(RCTUIManager *)manager performMountingWithBlock:(RCTUIManagerMountingBlock)block;
/**
* Called just after flushing UI blocks.
* This is called from the UIManager queue.

View File

@ -72,6 +72,20 @@
}
}
- (BOOL)uiManager:(RCTUIManager *)manager performMountingWithBlock:(RCTUIManagerMountingBlock)block
{
std::lock_guard<std::mutex> lock(_mutex);
for (id<RCTUIManagerObserver> observer in _observers) {
if ([observer respondsToSelector:@selector(uiManager:performMountingWithBlock:)]) {
if ([observer uiManager:manager performMountingWithBlock:block]) {
return YES;
}
}
}
return NO;
}
- (void)uiManagerDidPerformMounting:(RCTUIManager *)manager
{
std::lock_guard<std::mutex> lock(_mutex);