-
-
Notifications
You must be signed in to change notification settings - Fork 530
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
iOS 15 - function deinit not called on custom native components on goback #2007
Comments
Hey @delphinebugner,
What is your setup? Do you use RN only in part of your application, or is it standard RN app? Honestly I'm baffled, as the strong reference should be dropped once it goes out of the scope (after the function end), this is an automatic variable 😅 Thanks for reporting, we will investigate it. |
The sheet variable is not cleared after function end as it is used inside |
Hi @delphinebugner! I'm trying to reproduce this issue and I've stumbled upon some questions, while trying to do my own repro:
Also, even if I'm trying to do something with this PR, could you try to create a minimal repro with the two screens that show such behaviour? Of course it's not necessary to put your own video controller there, if it's possible to reproduce that leak in other components 😁 |
Thanks @tboba for working on this!
const RootStack = createNativeStackNavigator<RootStackParamList>();
<RootStack.Navigator screenOptions={{ header: CustomRootStackHeader, orientation: isTablet() ? 'all' : 'portrait_up'}}>
<RootStack.Screen
name={Routes.BASEPAGE}
component={BasePage} // 🐞 Unmounting this screen, video player inside is not deinit
getId={({ params }) => params.pageLink}
/>
...
type RootStackParamList = {
[Routes.BASEPAGE]: { pageLink: string };
...
};
|
@delphinebugner great, thanks! Yeah, it's quite weird that |
Okay I finally did it, the repro is here: https://github.com/delphinebugner/react-native-repro-deinit-15-old-arch Follow the instruction in the readme to see it happen! It's in old arch only, I will check now how it works with new arch! It's longer to reproduce as there is no Swift template for Fabric component, but it may be the same with the ObjectiveC |
@delphinebugner Great, thanks for that! I really also appreciate the explanation in README! 🙏 I'll let you know if we would have any other questions. |
+1 on this one, we were not getting a UIView dealloc when navigating back and forth from a screen. |
@tboba Any ideas when we might see a fix for this? Thank you for your work! |
I tried today with With iOS 15.5, old arch, classic stack! Thanks @tboba you were right about V4 :) -> @konradgap you can check! I don't know what screen's presentation you use, I hope it's working for you too cc @tomekzaw that was the one 👀 |
Happy to hear that the issue has been solved! |
Description
Thanks for working on this project! This bug is reaaally weird and it could be a memory leak on iOS 15. I only patched a workaround on my project, I do want your advice on it!
Bug
TL;DR: on iOS 15, after we upgraded RNScreens from 3.5 to 3.25, our custom bridged player continued to play after the destruction of its screen.
Here is a demo (turn the sound on!):
Bug_player-not-deinit_small.mov
Not iOS 14 neither iOS 16 ou 17. We still have around ~15% of our users on iOS 15 so it was important to fix.
Investigation
Our custom bridged player has its own
deinit
function in Swift, equivalent todealloc
in objective C++:On iOS 15, since version 3.19 of RNScreens, we saw that we did not enter the
deinit
function of the player when its screen was destroyed (= after a go-back in our native stack). Therefore its sound continued to play.We do enter the deinit function when we destroy the player alone, keeping the screen around it.
After bisecting the version, we saw that this PR introduces the regression: #1649.
More precisely, it's this line of RNSScreen.mm that introduces the leak :
react-native-screens/ios/RNSScreen.mm
Line 618 in e0bbf77
Just creating the *sheet pointer is enough to introduce the bug, even without the sheet being actually used after. I'm not a native expert but i think we can see it in this memory graph on XCode that the "UISnoopController" (=> its the one managing our player sound) is still attached to a _PageSheetPresentationController (our *sheet!); it could explain why we still hear the video sound:
Fix
It's a workaround: because we do not use the
PresentationFormSheet
in my app, I simply moved the line where we create the*sheet
pointer inside of the if:Here is an example of a go-back on iOS 15 with video sound properly disappearing:
Fixed_player-deinit.mov
Next steps
Steps to reproduce
The bug is currently in production on my app : https://apps.apple.com/fr/app/tf1-info-lci-actualit%C3%A9s/id426125722
Download it on an iPhone 15 and enjoy multiple sound superposing when doing go-backs!! 🥳
More seriously, I do not have a small reproduction yet, and can't share the full code as it belongs to a private company ; but if you judge it necessary I can try to work on it! (the URL provided s a sandbox but without repro in it)
Snack or a link to a repository
https://github.com/delphinebugner/expo-bac-a-sable
Screens version
3.29.0
React Native version
0.73.2
Platforms
iOS
JavaScript runtime
Hermes
Workflow
React Native (without Expo)
Architecture
Paper (Old Architecture)
Build type
None
Device
iOS simulator
Device model
iOS 15 only (neither 14 nor 16) ; real device & simulator
Acknowledgements
Yes
The text was updated successfully, but these errors were encountered: