Skip to content

Commit

Permalink
fix(iOS): look through whole ancestor chain when looking for screenvi…
Browse files Browse the repository at this point in the history
…ew from content wrapper (#2683)

## Description

In #2670 I've added a check that logged RN error in case
`contentWrapper.reactSuperview` is not a `RNSScreenView`.
Now I got reports (but no reproduction :/) from two independent sources
that this error is triggered pretty often,
which is unexpected from my perspective. I blindly blame view flattening
/ usage of legacy navigators but can not be sure.

This PR is an attempt to patch this behaviour.

## Changes

contentWrapper now searches whole view ancestor chain before logging an
error.

## Test code and steps to reproduce

No reproducer :/ 

## Checklist

- [ ] Included code example that can be used to test this change
- [ ] Updated TS types
- [ ] Updated documentation: <!-- For adding new props to native-stack
-->
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx
- [ ]
https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx
- [ ] Ensured that CI passes
  • Loading branch information
kkafar authored Feb 11, 2025
1 parent 2ca38af commit 21aca32
Showing 1 changed file with 19 additions and 4 deletions.
23 changes: 19 additions & 4 deletions ios/RNSScreenContentWrapper.mm
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,30 @@ - (void)attachToAncestorScreenViewStartingFrom:(nonnull RNSScreen *)screenCtrl

- (void)attachToAncestorScreenView
{
if (![self.reactSuperview isKindOfClass:RNSScreenView.class]) {
RCTLogError(@"Expected reactSuperview to be a RNSScreenView. Found %@", self.reactSuperview);
RNSScreen *_Nullable screen =
static_cast<RNSScreen *_Nullable>([[self findFirstScreenViewAncestor] reactViewController]);
if (screen == nil) {
RCTLogError(@"Failed to find parent screen controller from %@.", self);
return;
}

RNSScreen *screen = (RNSScreen *)[self.reactSuperview reactViewController];
[self attachToAncestorScreenViewStartingFrom:screen];
}

- (nullable RNSScreenView *)findFirstScreenViewAncestor
{
UIView *currentView = self;

// In standard scenario this should do only a single iteration.
// Haven't got repro, but we got reports that there are scenarios
// when there are intermediate views between screen view & the content wrapper.
// https://github.com/software-mansion/react-native-screens/pull/2683
do {
currentView = currentView.reactSuperview;
} while (currentView != nil && ![currentView isKindOfClass:RNSScreenView.class]);

return static_cast<RNSScreenView *_Nullable>(currentView);
}

#ifdef RCT_NEW_ARCH_ENABLED

#pragma mark - RCTComponentViewProtocol
Expand Down

0 comments on commit 21aca32

Please sign in to comment.