Last focused view's reference is held even after it's detached from window
See original GitHub issueDescription
RCTRootViewInternal.h helds strong reference to preferred focus view:
@property (nonatomic, strong) UIView *reactPreferredFocusedView;
which is saved each time hasTVPreferredFocus is used to focus element (RCTTVView.m):
- (void)setHasTVPreferredFocus:(BOOL)hasTVPreferredFocus
{
_hasTVPreferredFocus = hasTVPreferredFocus;
if (hasTVPreferredFocus) {
dispatch_async(dispatch_get_main_queue(), ^{
UIView *rootview = self;
while (![rootview isReactRootView] && rootview != nil) {
rootview = [rootview superview];
}
if (rootview == nil)
return;
rootview = [rootview superview];
[(RCTRootView *)rootview setReactPreferredFocusedView:self]; /// <------ THIS LINE
[rootview setNeedsFocusUpdate];
[rootview updateFocusIfNeeded];
});
}
}
Due to reactPreferredFocusedView being strong reference, it’s not released even if element unmounts. This leads to bugs in my code, as I base some of native focus management on native code, where I store last focused element as a weak reference to UIView, to be able to restore remembered focus in given views.
I obviously can verify, whether remembered UIView is attached to window (view.window == nil), and ignore it if not. However, holding strong reference to detached UIView still seems like a bug and a minor memory leak.
Version
0.66.3-1
Output of npx react-native info
System: OS: macOS 12.0.1 CPU: (16) x64 Intel® Core™ i9-9880H CPU @ 2.30GHz Memory: 33.57 MB / 32.00 GB Shell: 5.8 - /bin/zsh Binaries: Node: 16.13.2 - /usr/local/bin/node Yarn: 1.22.10 - /usr/local/bin/yarn npm: 8.1.2 - /usr/local/bin/npm Watchman: 2022.02.14.00 - /usr/local/bin/watchman Managers: CocoaPods: 1.11.3 - /Users/CENSORED/.rbenv/shims/pod SDKs: iOS SDK: Platforms: DriverKit 21.2, iOS 15.2, macOS 12.1, tvOS 15.2, watchOS 8.3 Android SDK: API Levels: 28, 29, 30, 31 Build Tools: 28.0.3, 29.0.2, 29.0.3, 30.0.2 System Images: android-28 | Android TV Intel x86 Atom, android-28 | Google Play Intel x86 Atom, android-29 | Google APIs Intel x86 Atom, android-31 | Android TV Intel x86 Atom, android-31 | Google APIs Intel x86 Atom_64, android-Q | Android TV Intel x86 Atom Android NDK: Not Found IDEs: Android Studio: 2021.1 AI-211.7628.21.2111.8193401 Xcode: 13.2.1/13C100 - /usr/bin/xcodebuild Languages: Java: 1.8.0_231 - /Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/bin/javac npmPackages: @react-native-community/cli: Not Found react: 17.0.2 => 17.0.2 react-native: Not Found react-native-macos: Not Found react-native-tvos: 0.66.3-1 npmGlobalPackages: react-native: Not Found
Steps to reproduce
Use hasTVPreferred focus on element, unmount it, go to XCode, verify memory graph:
Snack, code example, screenshot, or link to a repository
No response
Issue Analytics
- State:
- Created a year ago
- Comments:7 (4 by maintainers)
Top GitHub Comments
Thanks a lot for blazing fast response and review!
Thanks for quick response!
Isn’t it just dealloc for RCTRootView? Remounting RCTRootView is not a part of above reproduction, just some far nested views.