Skip to content

Commit 402ae2f

Browse files
sherginfacebook-github-bot
authored andcommittedFeb 21, 2018
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
1 parent 60c0000 commit 402ae2f

File tree

3 files changed

+46
-8
lines changed

3 files changed

+46
-8
lines changed
 

‎React/Modules/RCTUIManager.m

+23-8
Original file line numberDiff line numberDiff line change
@@ -1081,21 +1081,36 @@ - (void)flushUIBlocksWithCompletion:(void (^)(void))completion;
10811081
return;
10821082
}
10831083

1084-
// Execute the previously queued UI blocks
1085-
RCTProfileBeginFlowEvent();
1086-
RCTExecuteOnMainQueue(^{
1087-
RCTProfileEndFlowEvent();
1088-
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"-[UIManager flushUIBlocks]", (@{
1089-
@"count": [@(previousPendingUIBlocks.count) stringValue],
1090-
}));
1084+
__weak typeof(self) weakSelf = self;
1085+
1086+
void (^mountingBlock)(void) = ^{
1087+
typeof(self) strongSelf = weakSelf;
1088+
10911089
@try {
10921090
for (RCTViewManagerUIBlock block in previousPendingUIBlocks) {
1093-
block(self, self->_viewRegistry);
1091+
block(strongSelf, strongSelf->_viewRegistry);
10941092
}
10951093
}
10961094
@catch (NSException *exception) {
10971095
RCTLogError(@"Exception thrown while executing UI block: %@", exception);
10981096
}
1097+
};
1098+
1099+
if ([self.observerCoordinator uiManager:self performMountingWithBlock:mountingBlock]) {
1100+
completion();
1101+
return;
1102+
}
1103+
1104+
// Execute the previously queued UI blocks
1105+
RCTProfileBeginFlowEvent();
1106+
RCTExecuteOnMainQueue(^{
1107+
RCTProfileEndFlowEvent();
1108+
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways, @"-[UIManager flushUIBlocks]", (@{
1109+
@"count": [@(previousPendingUIBlocks.count) stringValue],
1110+
}));
1111+
1112+
mountingBlock();
1113+
10991114
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"");
11001115

11011116
RCTExecuteOnUIManagerQueue(completion);

‎React/Modules/RCTUIManagerObserverCoordinator.h

+9
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
#import <React/RCTViewManager.h>
1111

12+
typedef dispatch_block_t RCTUIManagerMountingBlock;
13+
1214
/**
1315
* Allows hooking into UIManager internals. This can be used to execute code at
1416
* specific points during the view updating process.
@@ -43,6 +45,13 @@
4345
*/
4446
- (void)uiManagerWillPerformMounting:(RCTUIManager *)manager;
4547

48+
/**
49+
* Called right before flushing UI blocks and allows to intercept the mounting process.
50+
* Return `YES` to cancel default execution of the `block` (and perform the
51+
* execution later).
52+
*/
53+
- (BOOL)uiManager:(RCTUIManager *)manager performMountingWithBlock:(RCTUIManagerMountingBlock)block;
54+
4655
/**
4756
* Called just after flushing UI blocks.
4857
* This is called from the UIManager queue.

‎React/Modules/RCTUIManagerObserverCoordinator.mm

+14
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,20 @@ - (void)uiManagerWillPerformMounting:(RCTUIManager *)manager
7272
}
7373
}
7474

75+
- (BOOL)uiManager:(RCTUIManager *)manager performMountingWithBlock:(RCTUIManagerMountingBlock)block
76+
{
77+
std::lock_guard<std::mutex> lock(_mutex);
78+
79+
for (id<RCTUIManagerObserver> observer in _observers) {
80+
if ([observer respondsToSelector:@selector(uiManager:performMountingWithBlock:)]) {
81+
if ([observer uiManager:manager performMountingWithBlock:block]) {
82+
return YES;
83+
}
84+
}
85+
}
86+
return NO;
87+
}
88+
7589
- (void)uiManagerDidPerformMounting:(RCTUIManager *)manager
7690
{
7791
std::lock_guard<std::mutex> lock(_mutex);

0 commit comments

Comments
 (0)
Please sign in to comment.