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}