2015-02-20 5 views
5

ich den Rat in mehreren SO Fragen zur Verfügung befolgt habe, wie this one, um MKMapView aus dem Speicher freizugeben - meinen Code untenMKMapView Release Speicher

- (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; 
} 

In Teil, es funktioniert, aber nicht ganz. Lassen Sie mich einige Daten bereitstellen.

Unten ist die Speicherzuweisung Aufnahme von Instruments.

enter image description here

Die beiden roten Fahnen (Generationen) zeigen die Zustände, bevor ich MKMapView in einem modalen View-Controller angezeigt und nachdem ich sie entlassen haben. MKMapView scheint freigegeben zu werden. Wenn ich zum Beispiel Statistikstacks in Instrumente für MKMapView filtere, erscheint das Objekt tatsächlich, wenn die modale Ansicht angezeigt wird, und verschwindet, sobald es geschlossen ist. Nachdem ich jedoch die Kartenansicht ausgeblendet habe, habe ich immer noch mehr als 30 MB Speicher, der nicht freigegeben wurde.

Die Daten der Generation B (zweite rote Flagge) zeigen, dass eine große Anzahl von Objekten (und Nicht-Objekten) diesen Speicher enthält.

enter image description here

Wenn ich längere Details eines dieser Instanzen betrachten, zeigt es in der Regel ein Stack-Trace, die private Klassen verfügt, die, glaube ich, sind das enter image description here

Zeichnung zur Karte

Weiß jemand, Wie kann man all diese Daten freigeben? Gibt es einen Cache, den ich putzen könnte/sollte?

+0

haben Sie es geschafft, dieses Problem zu lösen? – azimov

+0

Leider noch nicht .. – artooras

+0

Haben Sie Glück dabei, den Speicher zu löschen? – sridvijay

Antwort

1

In meiner App, die den Map-View-Controller unter Kontrolle eines Tab-View-Controllers verwendet, speichere ich eine Referenz auf eine MKMapView in einer statischen Variablen und benutze dieselbe Map-Ansicht immer wieder, anstatt eine neue zuzuweisen ViewDidLoad jedes Mal. Mein (teilweise) Code:

@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]; 
} 

Hier configureView: setzt die Karte für self.tabBarController.detailItem auf, setzt seinen Delegaten und speichert die Karte Annotationen in Variable annotations.

Die Karte wird als Unteransicht einer im Schnittstellen-Generator definierten Ansicht erstellt (Instanzvariable @property (weak, nonatomic) IBOutlet UIView *mapViewProxy;). Die Karte muss die gleiche Größe wie mapViewProxy haben, und wenn ich das automatische Layout verwende, wird die Rahmengröße von _mapView vollständig unter Verwendung der in festgelegten Einschränkungen (oben, unten, links und rechts gleich _mapView.superview) gesteuert.

Ich fand es obligatorisch, die Anmerkungen aus der Karte in viewDidDisppear: zu entfernen und sie wieder in viewDidAppear hinzuzufügen. Es könnte sogar noch sauberer sein, _mapView.delegate in viewDidDisppear: zu löschen und in viewDidAppear zurückzusetzen.

BTW: Die statische Variable _mapView trägt immer noch irreführend den führenden Unterstrich, da es vor der Einrichtung eine Instanzvariable war, indem MKMapView in IB definiert wurde.

0

Dies ist die Lösung, die ich verwendet habe und es funktioniert gut. Ich denke, dieses Problem wurde erst kürzlich eingeführt, weil ich noch keine Probleme mit der Zuordnung der Map zuvor innerhalb des gleichen Projekts hatte.

Ich habe die Karteninstanz in einem Singleton gespeichert und einfach nach ihrer Existenz gesucht, bevor ich eine neue erstellt habe. dh:

if let existingMapView = LocationSingleton.sharedInstance.singletonMapView { 

    //Display map 
}else{ 

    let newMapView = //Instantiate new map view controller 
    LocationSingleton.sharedInstance.singletonMapView = newMapView 

    //Display map 
}