Commit 71db286
committed
fix(iOS,Fabric): prevent memory leak by calling
On new architecture there is no callback that notifies components that
they're deleted
and won't be used anymore. `RCTComponentViewProtocol#prepareForRecycle`
was supposed to fulfill
this role, however after it became possible to disable view recycling
for given class of components,
it is not always called.
In our case, we need such callback in `Screen` to break the retain
(strong reference) cycle between `ScreenView` and its `Screen`
(controller),
otherwise we leak the `RNSScreenView` and `RNSScreen` instances.
Overrode the `mountingTransactionWillMount:withSurfaceTelemetry:` in
`RNSScreenStack`, where screens that are meant to receive
`Delete` mutation are retained, and later in
`mountingTransactionDidMount:withSurfaceTelemetry:` we dispatch a series
of `invalidate` calls & release the components.
<img width="557" alt="image"
src="https://github.com/user-attachments/assets/546050e2-5eeb-4c2f-b0f9-5d1d4212889d">
<img width="539" alt="image"
src="https://github.com/user-attachments/assets/e92a2778-b7c0-41e6-9ebb-68a8270aa786">
> [!note]
> Please note, that these screenshots are done with a patch presented
below 👇🏻, w/o it, the memory leak is not that big.
Added `TestMemoryLeak` test screen to our example app. The easiest way
to test this is to apply following patch:
<details>
<summary>See bigFatMemoryChunk</summary>
```c
diff --git a/ios/RNSScreen.mm b/ios/RNSScreen.mm
index 6d06949..0e3a572b5 100644
--- a/ios/RNSScreen.mm
+++ b/ios/RNSScreen.mm
@@ -61,6 +61,7 @@ constexpr NSInteger SHEET_LARGEST_UNDIMMED_DETENT_NONE = -1;
@implementation RNSScreenView {
__weak ReactScrollViewBase *_sheetsScrollView;
BOOL _didSetSheetAllowedDetentsOnController;
+ NSMutableArray<UIView *> *bigFatMemoryChunk;
#ifdef RCT_NEW_ARCH_ENABLED
RCTSurfaceTouchHandler *_touchHandler;
react::RNSScreenShadowNode::ConcreteState::Shared _state;
@@ -89,7 +90,12 @@ constexpr NSInteger SHEET_LARGEST_UNDIMMED_DETENT_NONE = -1;
_props = defaultProps;
_reactSubviews = [NSMutableArray new];
_contentWrapper = nil;
+ bigFatMemoryChunk = [[NSMutableArray alloc] init];
+ for (int i = 0; i < 1024 * 5; ++i) {
+ [bigFatMemoryChunk addObject:[[UIView alloc] initWithFrame:frame]];
+ }
[self initCommonProps];
+// NSLog(@"[ALLOC][%ld] %p, memory chunk at %p, %@", self.tag, self, bigFatMemoryChunk, bigFatMemoryChunk[1023]);
}
return self;
}
@@ -753,6 +759,7 @@ constexpr NSInteger SHEET_LARGEST_UNDIMMED_DETENT_NONE = -1;
{
_controller = nil;
[_sheetsScrollView removeObserver:self forKeyPath:@"bounds" context:nil];
+ [bigFatMemoryChunk removeAllObjects];
}
#if !TARGET_OS_TV && !TARGET_OS_VISION
```
</details>
Try to remove call to `[strongSelf invalidate]` in
`mountingTransactionDidMount:withSurfaceTelemetry:` and see that the
screens are indeed retained indefinitely.
- [x] Included code example that can be used to test this change
- [ ] Ensured that CI passes
(cherry picked from commit a116e7d)invalidate on deleted screens (#2402)1 parent 652dbcf commit 71db286
File tree
5 files changed
+124
-4
lines changed- apps/src/tests
- ios
5 files changed
+124
-4
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
115 | 115 | | |
116 | 116 | | |
117 | 117 | | |
| 118 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
131 | 131 | | |
132 | 132 | | |
133 | 133 | | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
134 | 142 | | |
135 | 143 | | |
136 | 144 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
614 | 614 | | |
615 | 615 | | |
616 | 616 | | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
617 | 623 | | |
618 | 624 | | |
619 | 625 | | |
| |||
859 | 865 | | |
860 | 866 | | |
861 | 867 | | |
862 | | - | |
863 | | - | |
864 | | - | |
865 | | - | |
866 | 868 | | |
867 | 869 | | |
868 | 870 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
120 | 120 | | |
121 | 121 | | |
122 | 122 | | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
123 | 130 | | |
124 | 131 | | |
125 | 132 | | |
| |||
1118 | 1125 | | |
1119 | 1126 | | |
1120 | 1127 | | |
| 1128 | + | |
| 1129 | + | |
| 1130 | + | |
| 1131 | + | |
| 1132 | + | |
| 1133 | + | |
| 1134 | + | |
| 1135 | + | |
| 1136 | + | |
| 1137 | + | |
1121 | 1138 | | |
1122 | 1139 | | |
1123 | 1140 | | |
| |||
1151 | 1168 | | |
1152 | 1169 | | |
1153 | 1170 | | |
| 1171 | + | |
| 1172 | + | |
| 1173 | + | |
| 1174 | + | |
| 1175 | + | |
| 1176 | + | |
| 1177 | + | |
| 1178 | + | |
| 1179 | + | |
| 1180 | + | |
| 1181 | + | |
| 1182 | + | |
| 1183 | + | |
1154 | 1184 | | |
1155 | 1185 | | |
1156 | 1186 | | |
| |||
1167 | 1197 | | |
1168 | 1198 | | |
1169 | 1199 | | |
| 1200 | + | |
| 1201 | + | |
| 1202 | + | |
| 1203 | + | |
| 1204 | + | |
| 1205 | + | |
| 1206 | + | |
| 1207 | + | |
| 1208 | + | |
| 1209 | + | |
| 1210 | + | |
| 1211 | + | |
| 1212 | + | |
| 1213 | + | |
| 1214 | + | |
1170 | 1215 | | |
1171 | 1216 | | |
1172 | 1217 | | |
| |||
0 commit comments