-
-
Notifications
You must be signed in to change notification settings - Fork 532
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: memory leak due to retain cycle between view & controller #1797
Conversation
751aab5
to
cdaf777
Compare
@kkafar I've patched diff --git a/node_modules/react-native-screens/ios/RNSScreen.mm b/node_modules/react-native-screens/ios/RNSScreen.mm
index d6975f7..0765cac 100644
--- a/node_modules/react-native-screens/ios/RNSScreen.mm
+++ b/node_modules/react-native-screens/ios/RNSScreen.mm
@@ -571,6 +571,11 @@
}
#endif // !TARGET_OS_TV
+- (void)releaseViewController
+{
+ _controller = nil;
+}
+
#pragma mark - Fabric specific
#ifdef RCT_NEW_ARCH_ENABLED
@@ -769,7 +774,7 @@
- (void)invalidate
{
- _controller = nil;
+ [self releaseViewController];
}
#endif
@@ -921,6 +926,18 @@ Class<RCTComponentViewProtocol> RNSScreenCls(void)
#else
[self traverseForScrollView:self.screenView];
#endif
+
+ // See: https://github.com/software-mansion/react-native-screens/pull/1797
+ // In brownfield applications there are some flows in which React Native mechanisms
+ // of invalidating the views are not called, resulting in memory leak on our side,
+ // as RNSScreenView holds strong reference to a RNSScreen, thus they both can not be
+ // released.
+ UINavigationController *navigationController = self.navigationController;
+ BOOL isGoingForward =
+ [navigationController isBeingDismissed] || [navigationController isMovingFromParentViewController];
+ if (!isGoingForward || !_goingForward) {
+ [self.screenView releaseViewController];
+ }
}
- (void)viewDidLayoutSubviews but when I video demo with xcode breakpointsScreen.Recording.2023-07-11.at.10.51.00.mov |
cdaf777
to
dea12de
Compare
@@ -951,6 +956,18 @@ - (void)viewDidDisappear:(BOOL)animated | |||
#else | |||
[self traverseForScrollView:self.screenView]; | |||
#endif | |||
|
|||
// See: https://github.com/software-mansion/react-native-screens/pull/1797 | |||
// In brownfield appliactions there are some flows in which React Native mechanisms |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo appliactions
-> applications
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, I've moved fix of this issue to react native's repository: facebook/react-native#38617
Hey @efstathiosntonas, Most likely I won't merge this PR, but I'm leaving it open in case I have to come with some workarounds in this library as the changes this PR introduces are not sufficient (and they do break other things) |
Thanks for the update @kkafar! keep it up! |
Hey, as my PR to React Native is merged I'm closing the PR. |
@kkafar I see the PR made it to production, however, I don't see your changes in We are experiencing a memory leak potentially related to RNS in some of our apps, I wanted to root that out and test your fix. I am on:
unfortunately when I tested your PR branch I experienced a crash:
coming from RNSScreenContainer Are you aware what happened to your changes? We just updated from RN 0.73.6 in hopes that memory management would improve. |
Description
In our Paper code we rely on React Native to invalidate our views* -- that always happens when changes in view hierarchy are triggered by JS side (standard React Native application). However in brownfield applications (iOS) there are some flows in which React Native cleanup (see
RCTInvalidate
protocol) does not get triggered (see #1754 for context).* The cleanup is required because
RNSScreenView
retainsRNSScreen
by holding a reference. Ininvalidate
method ofRNSScreenView
we just release the controller by setting_controller = nil
.Closes #1754
Changes
Added check in
viewDidDisappear
method for situation when whole navigation controller gets dismissed and if so, we manually release view controller.Checklist