MKMapView libérer la memory

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.

entrez la description de l'image ici

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.

entrez la description de l'image ici

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 entrez la description de l'image ici

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 }