Stop iOS 7 MKMapView from leaking memory Stop iOS 7 MKMapView from leaking memory objective-c objective-c

Stop iOS 7 MKMapView from leaking memory


I had faced the same issue and (thanks to Stackoverflow) fixed it by changing MKMapType in viewWillDisappear and deallocating/setting its delegate to nil.As it still sends message to delegates.This is documented in MKMapViewDelegate Protocol Reference:

Before releasing an MKMapView object for which you have set a delegate, remember to set that object’s delegate property to nil. One place you can do this is in the dealloc method where you dispose of the map view

.

-(void)viewWillDisappear:(BOOL)animated{  [super viewWillDisappear:animated];  [self applyMapViewMemoryFix];}- (void)applyMapViewMemoryFix{switch (self.mkMapView.mapType) {    case MKMapTypeHybrid:    {        self.mkMapView.mapType = MKMapTypeStandard;    }        break;    case MKMapTypeStandard:    {        self.mkMapView.mapType = MKMapTypeHybrid;    }        break;    default:        break;}self.mkMapView.showsUserLocation = NO;self.mkMapView.delegate = nil;[self.mkMapView removeFromSuperview];self.mkMapView = nil;}

hope this helps


The best solution I have found is to have an instance of MKMapView in your delegate, you will allocate it only once.

Then anytime you need a MapView, you just use the one from the delegate.

In my case i needed to clean the annotations from it as soon as the view willDisappear ( to not have older annotations on the map ).

  - (void)viewDidLoad {      AppDelegate *delegate = [UIApplication sharedApplication].delegate;          if (!delegate.appModel.mapView)             delegate.appModel.mapView = [[MKMapView alloc] initWithFrame:self.view.frame];      self.mapView = delegate.appModel.mapView;      [self.mapView setFrame:self.view.frame];      [self.mapView setDelegate:self];      [self.view addSubview:self.mapView];   }- (void)viewWillDisappear:(BOOL)animated {    [super viewWillDisappear:animated];    [self.mapView removeAnnotations:self.mapView.annotations];    for (id<MKOverlay> overlay in self.mapView.overlays) {        [self.mapView removeOverlay:overlay];    }}


Swift Version:

override func viewWillDisappear(_ animated:Bool) {    super.viewWillDisappear(animated)    self.applyMapViewMemoryFix()}func applyMapViewMemoryFix() {    switch (self.mapView.mapType) {    case MKMapType.hybrid:        self.mapView.mapType = MKMapType.standard    case MKMapType.standard:        self.mapView.mapType = MKMapType.hybrid    default:        break    }    self.mapView.showsUserLocation = false    self.mapView.delegate = nil    self.mapView.removeFromSuperview()    self.mapView = nil}