J'ai suivi le conseil disponible dans plusieurs questions SO, comme celui-ci , afin de libérer MKMapView
de la memory – mon code ci-dessous
- (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; self.map.mapType = MKMapTypeHybrid; self.map.showsUserLocation = NO; self.map.delegate = nil; [self.map removeFromSuperview]; self.map = nil; self.locationManager.delegate = nil; }
En partie, cela fonctionne, mais pas entièrement. Permettez-moi de fournir des données.
Voici l'logging de l'allocation de memory à partir d'Instruments.
Les deux drapeaux rouges (Générations) indiquent les états avant que MKMapView
dans un controller de vue modale et après que je l'ai rejeté. MKMapView
semble être désaffecté. Par exemple, si je filter la stack Statistics dans Instruments pour MKMapView
, l'object apparaît effectivement lorsque la vue modale est présentée, et disparaît une fois qu'il est fermé. Cependant, après avoir rejeté la vue de la carte, j'ai encore 30 Mo de memory qui n'a pas été libérée.
Les données de la génération B (second drapeau rouge) montrent qu'il existe un grand nombre d'objects (et de non-objects) qui contiennent cette memory.
Lorsque je regarde les détails étendus d'une de ces instances, il montre généralement une trace de stack qui comporte des classs privées qui, je suppose, sont liées au dessin de carte
Est-ce que quelqu'un sait comment libérer toutes ces données? Y a-t-il un cache que je pourrais / devrait nettoyer?
Dans mon application, qui utilise le controller de vue de carte sous le contrôle d'un controller d'tabs, je stocke une reference à un MKMapView
dans une variable statique et j'utilise cette même vue encore et encore au lieu d'en allouer un nouveau dans ViewDidLoad
chaque fois. Mon code (partiel):
@implementation PubMapViewController { NSMutableArray *annotations; } static MKMapView *_mapView = nil; - (void)viewDidLoad { [super viewDidLoad]; if (!_mapView) { _mapView = [[MKMapView alloc] init]; // frame set up with constraints } else { [_mapView removeAnnotations:_mapView.annotations]; // precaution } [_mapViewProxy addSubview:_mapView]; [self addConstraints:_mapView]; [self configureView:((PubTabBarController *)self.tabBarController).detailItem]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [_mapView addAnnotations:annotations]; if (annotations.count == 1) { [_mapView selectAnnotation:annotations[0] animated:YES]; } } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; [_mapView removeAnnotations:_mapView.annotations]; }
Ici, configureView:
la map pour self.tabBarController.detailItem
, définit son délégué et stocke les annotations de la carte dans les annotations
variables.
La carte est une sous-vue d'une vue définie dans le constructor de l'interface (variable d'instance @property (weak, nonatomic) IBOutlet UIView *mapViewProxy;
). La carte doit get la même taille que mapViewProxy
, et comme j'utilise autolayout, la taille d' _mapView
de _mapView
est entièrement contrôlée en utilisant les contraintes définies dans addConstraints
(haut, bas, gauche et droite égal à _mapView.superview
).
J'ai trouvé obligatoire de supprimer les annotations de la carte dans viewDidDisppear:
et de les rappend dans viewDidAppear
. Il serait peut-être encore plus _mapView.delegate
d' viewDidDisppear:
_mapView.delegate
dans viewDidDisppear:
et de le viewDidAppear
dans viewDidAppear
.
BTW: La variable statique _mapView
porte toujours _mapView
le trait de soulignement principal, car il s'agissait d'une variable d'instance avant d'être définie en définissant MKMapView
dans IB.
C'est la solution que j'ai utilisée et cela fonctionne bien. Je pense que ce problème n'a été introduit que récemment parce que je n'ai pas eu de problèmes avec la carte désallouer correctement avant dans le même projet.
J'ai stocké l'instance de carte dans un singleton et je vérifie simplement son existence avant d'en créer une nouvelle. c'est à dire:
if let existingMapView = LocationSingleton.sharedInstance.singletonMapView { //Display map }else{ let newMapView = //Instantiate new map view controller LocationSingleton.sharedInstance.singletonMapView = newMapView //Display map }