Skip to content

Commit

Permalink
Only execute update block once
Browse files Browse the repository at this point in the history
Summary:
We were executing all the updateBlocks for every frame that was updated in the UI flush. This would quickly give you an explosive number of block calls when loading complex views.

This update block is only really used by text to propagate padding, even though the actual insets are mostly just 0.

public

Reviewed By: nicklockwood

Differential Revision: D2848968

fb-gh-sync-id: e43c529c2bb9729e2b779bf4abefeed58775cc2e
  • Loading branch information
javache authored and facebook-github-bot-7 committed Feb 1, 2016
1 parent 97723e4 commit bb5a6be
Showing 1 changed file with 35 additions and 25 deletions.
60 changes: 35 additions & 25 deletions React/Modules/RCTUIManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,8 @@ - (RCTViewManagerUIBlock)uiBlockWithLayoutUpdateForRootView:(RCTShadowView *)roo
[NSMutableArray arrayWithCapacity:viewsWithNewFrames.count];
NSMutableArray<NSNumber *> *parentsAreNew =
[NSMutableArray arrayWithCapacity:viewsWithNewFrames.count];
NSMutableDictionary<NSNumber *, RCTViewManagerUIBlock> *updateBlocks =
[NSMutableDictionary new];

for (RCTShadowView *shadowView in viewsWithNewFrames) {
[frameReactTags addObject:shadowView.reactTag];
Expand All @@ -500,10 +502,13 @@ - (RCTViewManagerUIBlock)uiBlockWithLayoutUpdateForRootView:(RCTShadowView *)roo
// reactSetFrame: has been called. Note that if reactSetFrame: is not called,
// these won't be called either, so this is not a suitable place to update
// properties that aren't related to layout.
NSMutableArray<RCTViewManagerUIBlock> *updateBlocks = [NSMutableArray new];
for (RCTShadowView *shadowView in viewsWithNewFrames) {
RCTViewManager *manager = [_componentDataByName[shadowView.viewName] manager];
RCTViewManagerUIBlock block = [manager uiBlockToAmendWithShadowView:shadowView];
if (block) {
updateBlocks[shadowView.reactTag] = block;
}

if (shadowView.onLayout) {
CGRect frame = shadowView.frame;
shadowView.onLayout(@{
Expand All @@ -525,14 +530,9 @@ - (RCTViewManagerUIBlock)uiBlockWithLayoutUpdateForRootView:(RCTShadowView *)roo
RCTAssert(view != nil, @"view (for ID %@) not found", reactTag);

RCTRootView *rootView = (RCTRootView *)[view superview];

rootView.intrinsicSize = contentSize;
});
}

if (block) {
[updateBlocks addObject:block];
}
}

// Perform layout (possibly animated)
Expand Down Expand Up @@ -561,31 +561,18 @@ - (RCTViewManagerUIBlock)uiBlockWithLayoutUpdateForRootView:(RCTShadowView *)roo
}
};

// Animate view update
if (updateAnimation) {
[updateAnimation performAnimations:^{
[view reactSetFrame:frame];
for (RCTViewManagerUIBlock block in updateBlocks) {
block(self, _viewRegistry);
}
} withCompletionBlock:completion];
} else {
[view reactSetFrame:frame];
for (RCTViewManagerUIBlock block in updateBlocks) {
block(self, _viewRegistry);
}
completion(YES);
}

// Animate view creation
if (createAnimation) {
[view reactSetFrame:frame];

CATransform3D finalTransform = view.layer.transform;
CGFloat finalOpacity = view.layer.opacity;
if ([createAnimation.property isEqualToString:@"scaleXY"]) {
view.layer.transform = CATransform3DMakeScale(0, 0, 0);
} else if ([createAnimation.property isEqualToString:@"opacity"]) {
view.layer.opacity = 0.0;
}

[createAnimation performAnimations:^{
if ([createAnimation.property isEqual:@"scaleXY"]) {
view.layer.transform = finalTransform;
Expand All @@ -595,10 +582,33 @@ - (RCTViewManagerUIBlock)uiBlockWithLayoutUpdateForRootView:(RCTShadowView *)roo
RCTLogError(@"Unsupported layout animation createConfig property %@",
createAnimation.property);
}
for (RCTViewManagerUIBlock block in updateBlocks) {
block(self, _viewRegistry);

RCTViewManagerUIBlock updateBlock = updateBlocks[reactTag];
if (updateBlock) {
updateBlock(self, _viewRegistry);
}
} withCompletionBlock:completion];

// Animate view update
} else if (updateAnimation) {
[updateAnimation performAnimations:^{
[view reactSetFrame:frame];

RCTViewManagerUIBlock updateBlock = updateBlocks[reactTag];
if (updateBlock) {
updateBlock(self, _viewRegistry);
}
} withCompletionBlock:nil];
} withCompletionBlock:completion];

// Update without animation
} else {
[view reactSetFrame:frame];

RCTViewManagerUIBlock updateBlock = updateBlocks[reactTag];
if (updateBlock) {
updateBlock(self, _viewRegistry);
}
completion(YES);
}
}
};
Expand Down

0 comments on commit bb5a6be

Please sign in to comment.