Skip to content

Commit 3c589b1

Browse files
authored
refactor(iOS): update view controller once per transaction when adding header subviews (#2623)
## Description In #2466 I've introduced `RCTMountingTransactionObserving` for `RNSScreenStackHeaderConfig` component. Now we can use this to reduce amount of calls to `updateViewControllerIfNeeded` (causing layout passes) when adding subviews. I'm not changing the `unmount` path of the code as we have some more additional logic there which requires some more careful consideration. This also aligns us with Paper implementation. Note that it has been only implemented this way, because at the implementation time there was no way to run this code on transaction completion. ## Changes `- [RNSScreenStackHeaderConfig updateViewControllerIfNeeded]` is now called only once per transaction when adding subviews to header config. ## Test code and steps to reproduce Test432, TestHeaderTitle, Test2552 - see that there are no regressions. > [!note] During testing I've found that there is a bug with subview layout when modifying subviews after first render. This is not a regression however. Notice the wrong position of header right on video below 👇🏻 (Test432) https://github.com/user-attachments/assets/7f8653e8-a7d9-4fb8-a875-182e7deb0495 ## Checklist - [x] Included code example that can be used to test this change - [x] Ensured that CI passes
1 parent b69ea04 commit 3c589b1

File tree

1 file changed

+6
-5
lines changed

1 file changed

+6
-5
lines changed

ios/RNSScreenStackHeaderConfig.mm

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -883,9 +883,6 @@ - (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childCompone
883883
[self insertReactSubview:(RNSScreenStackHeaderSubview *)childComponentView atIndex:index];
884884

885885
_addedReactSubviewsInCurrentTransaction = true;
886-
887-
// TODO: This could be called only once per transaction.
888-
[self updateViewControllerIfNeeded];
889886
}
890887

891888
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
@@ -909,15 +906,19 @@ - (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childCompo
909906
- (void)mountingTransactionDidMount:(const facebook::react::MountingTransaction &)transaction
910907
withSurfaceTelemetry:(const facebook::react::SurfaceTelemetry &)surfaceTelemetry
911908
{
912-
if (_addedReactSubviewsInCurrentTransaction && self.shouldHeaderBeVisible) {
909+
if (_addedReactSubviewsInCurrentTransaction) {
910+
[self updateViewControllerIfNeeded];
911+
913912
// This call is made for the sake of https://github.com/software-mansion/react-native-screens/pull/2466.
914913
// In case header subview is added **after initial screen render** the system positions it correctly,
915914
// however `viewDidLayoutSubviews` is not called on `RNSNavigationController` and updated frame sizes of the
916915
// subviews are not sent to ShadowTree leading to issues with pressables.
917916
// Sending state update to ShadowTree from here is not enough, because native layout has not yet
918917
// happened after the child had been added. Requesting layout on navigation bar does not trigger layout callbacks
919918
// either, however doing so on main view of navigation controller does the trick.
920-
[self layoutNavigationControllerView];
919+
if (self.shouldHeaderBeVisible) {
920+
[self layoutNavigationControllerView];
921+
}
921922
}
922923
_addedReactSubviewsInCurrentTransaction = false;
923924
}

0 commit comments

Comments
 (0)