Enforcing sequential ordering of creating view and applying props in UIManager

Summary: See the comment in code.

Reviewed By: fkgozali

Differential Revision: D7014177

fbshipit-source-id: c58db856d7701a285564470eb1f024b5012dd451
This commit is contained in:
Valentin Shergin 2018-02-20 22:11:53 -08:00 committed by Facebook Github Bot
parent b90c1cf6c3
commit 60c000022e
1 changed files with 27 additions and 12 deletions

View File

@ -923,21 +923,36 @@ RCT_EXPORT_METHOD(createView:(nonnull NSNumber *)reactTag
// Dispatch view creation directly to the main thread instead of adding to
// UIBlocks array. This way, it doesn't get deferred until after layout.
__weak RCTUIManager *weakManager = self;
RCTExecuteOnMainQueue(^{
RCTUIManager *uiManager = weakManager;
if (!uiManager) {
__block UIView *preliminaryCreatedView = nil;
void (^createViewBlock)(void) = ^{
// Do nothing on the second run.
if (preliminaryCreatedView) {
return;
}
UIView *view = [componentData createViewWithTag:reactTag];
if (view) {
uiManager->_viewRegistry[reactTag] = view;
}
});
[self addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
UIView *view = viewRegistry[reactTag];
[componentData setProps:props forView:view];
preliminaryCreatedView = [componentData createViewWithTag:reactTag];
if (preliminaryCreatedView) {
self->_viewRegistry[reactTag] = preliminaryCreatedView;
}
};
// We cannot guarantee that asynchronously scheduled block will be executed
// *before* a block is added to the regular mounting process (simply because
// mounting process can be managed externally while the main queue is
// locked).
// So, we positively dispatch it asynchronously and double check inside
// the regular mounting block.
RCTExecuteOnMainQueue(createViewBlock);
[self addUIBlock:^(__unused RCTUIManager *uiManager, __unused NSDictionary<NSNumber *, UIView *> *viewRegistry) {
createViewBlock();
if (preliminaryCreatedView) {
[componentData setProps:props forView:preliminaryCreatedView];
}
}];
[self _shadowView:shadowView didReceiveUpdatedProps:[props allKeys]];