diff --git a/React/Base/RCTBatchedBridge.m b/React/Base/RCTBatchedBridge.m index a0190a0ae5..1999f32b02 100644 --- a/React/Base/RCTBatchedBridge.m +++ b/React/Base/RCTBatchedBridge.m @@ -982,6 +982,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR }]; } +- (BOOL)isBatchActive +{ + return _wasBatchActive; +} + @end @implementation RCTBatchedBridge(Deprecated) diff --git a/React/Base/RCTBridge.h b/React/Base/RCTBridge.h index 487773f521..f341b75aab 100644 --- a/React/Base/RCTBridge.h +++ b/React/Base/RCTBridge.h @@ -163,6 +163,11 @@ RCT_EXTERN BOOL RCTBridgeModuleClassIsRegistered(Class); */ - (void)reload; +/** + * Says whether bridge has started recieving calls from javascript. + */ +- (BOOL)isBatchActive; + @end /** diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m index 70bd92688e..c0b89be0a2 100644 --- a/React/Base/RCTBridge.m +++ b/React/Base/RCTBridge.m @@ -287,6 +287,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init) return self.batchedBridge.valid; } +- (BOOL)isBatchActive +{ + return [_batchedBridge isBatchActive]; +} + - (void)invalidate { RCTBatchedBridge *batchedBridge = self.batchedBridge; diff --git a/React/Modules/RCTUIManager.h b/React/Modules/RCTUIManager.h index dc0bcd9d98..bdcf2e2c53 100644 --- a/React/Modules/RCTUIManager.h +++ b/React/Modules/RCTUIManager.h @@ -88,6 +88,12 @@ RCT_EXTERN NSString *const RCTUIManagerRootViewKey; */ @property (atomic, assign) BOOL unsafeFlushUIChangesBeforeBatchEnds; +/** + * In some cases we might want to trigger layout from native side. + * React won't be aware of this, so we need to make sure it happens. + */ +- (void)setNeedsLayout; + @end /** diff --git a/React/Modules/RCTUIManager.m b/React/Modules/RCTUIManager.m index 4812a548ef..46c991e3c3 100644 --- a/React/Modules/RCTUIManager.m +++ b/React/Modules/RCTUIManager.m @@ -888,6 +888,15 @@ RCT_EXPORT_METHOD(findSubviewIn:(nonnull NSNumber *)reactTag atPoint:(CGPoint)po } - (void)batchDidComplete +{ + [self _layoutAndMount]; +} + +/** + * Sets up animations, computes layout, creates UI mounting blocks for computed layout, + * runs these blocks and all other already existing blocks. + */ +- (void)_layoutAndMount { // Gather blocks to be executed now that all view hierarchy manipulations have // been completed (note that these may still take place before layout has finished) @@ -962,6 +971,15 @@ RCT_EXPORT_METHOD(findSubviewIn:(nonnull NSNumber *)reactTag atPoint:(CGPoint)po } } +- (void)setNeedsLayout +{ + // If there is an active batch layout will happen when batch finished, so we will wait for that. + // Otherwise we immidiately trigger layout. + if (![_bridge isBatchActive]) { + [self _layoutAndMount]; + } +} + RCT_EXPORT_METHOD(measure:(nonnull NSNumber *)reactTag callback:(RCTResponseSenderBlock)callback) {