Skip to content

Commit 7150e98

Browse files
g4rb4g3mathieupost
authored andcommitted
Bugfix/unmount memory leak (rnmapbox#3708)
* fix: memory not freed up when component mapview is unmounted * add (un)mount to Show Map example * update (un-)mount example * generate
1 parent 7a91212 commit 7150e98

File tree

4 files changed

+79
-1
lines changed

4 files changed

+79
-1
lines changed

docs/examples.json

+10
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,16 @@
260260
"relPath": "Map/MapAndRNNavigation.js",
261261
"name": "MapAndRNNavigation"
262262
},
263+
{
264+
"metadata": {
265+
"title": "Map (un-)mount",
266+
"tags": [],
267+
"docs": "\nShowing and hiding the the map should not lead to increased memory consumption, use this example to check it on the profiler.\n"
268+
},
269+
"fullPath": "example/src/examples/Map/MapUnMount.tsx",
270+
"relPath": "Map/MapUnMount.tsx",
271+
"name": "MapUnMount"
272+
},
263273
{
264274
"metadata": {
265275
"title": "Offline Example",
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import React, { useState, useEffect } from 'react';
2+
import Mapbox from '@rnmapbox/maps';
3+
import { Button } from '@rneui/base';
4+
5+
import sheet from '../../styles/sheet';
6+
import { ExampleWithMetadata } from '../common/ExampleMetadata'; // exclude-from-doc
7+
8+
const MapUnMount = () => {
9+
const [isMounted, setIsMounted] = useState(true);
10+
11+
useEffect(() => {
12+
Mapbox.locationManager.start();
13+
14+
return (): void => {
15+
Mapbox.locationManager.stop();
16+
};
17+
}, []);
18+
19+
return (
20+
<>
21+
<Button
22+
onPress={() => setIsMounted((mounted) => !mounted)}
23+
title={isMounted ? 'unmount MapView' : 'mount MapView'}
24+
/>
25+
{isMounted ? (
26+
<Mapbox.MapView
27+
styleURL={Mapbox.StyleURL.Dark}
28+
style={sheet.matchParent}
29+
testID={'show-map'}
30+
>
31+
<Mapbox.Camera followZoomLevel={12} followUserLocation />
32+
33+
<Mapbox.UserLocation />
34+
</Mapbox.MapView>
35+
) : null}
36+
</>
37+
);
38+
};
39+
40+
export default MapUnMount;
41+
42+
/* end-example-doc */
43+
44+
const metadata: ExampleWithMetadata['metadata'] = {
45+
title: 'Map (un-)mount',
46+
tags: [],
47+
docs: `
48+
Showing and hiding the the map should not lead to increased memory consumption, use this example to check it on the profiler.
49+
`,
50+
};
51+
MapUnMount.metadata = metadata;

example/src/examples/Map/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export { default as PointInMapView } from './PointInMapView';
66
export { default as ShowAndHideLayer } from './ShowAndHideLayer';
77
export { default as ShowClick } from './ShowClick';
88
export { default as ShowMap } from './ShowMap';
9+
export { default as MapUnMount } from './MapUnMount';
910
export { default as ShowMapLocalStyle } from './ShowMapLocalStyle';
1011
export { default as ShowRegionDidChange } from './ShowRegionDidChange';
1112
export { default as SourceLayerVisibility } from './SourceLayerVisibility';

ios/RNMBX/RNMBXMapView.swift

+17-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,23 @@ class RNMBXCameraChanged : RNMBXEvent, RCTEvent {
154154
}
155155

156156
@objc(RNMBXMapView)
157-
open class RNMBXMapView: UIView {
157+
open class RNMBXMapView: UIView, RCTInvalidating {
158+
159+
public func invalidate() {
160+
self.removeAllFeaturesFromMap(reason: .ViewRemoval)
161+
162+
#if RNMBX_11
163+
cancelables.forEach { $0.cancel() }
164+
cancelables.removeAll()
165+
#endif
166+
167+
_mapView.gestures.delegate = nil
168+
_mapView.removeFromSuperview()
169+
_mapView = nil
170+
171+
self.removeFromSuperview()
172+
}
173+
158174
var imageManager: ImageManager = ImageManager()
159175

160176
var tapDelegate: IgnoreRNMBXMakerViewGestureDelegate? = nil

0 commit comments

Comments
 (0)