iOS removing MKMapView overlays not working
Asked Answered
A

3

10

I would like to remove all the overlays of my map at one point, and I tried different ways but it never works.

Last try I did [self.mapView removeOverlays:self.mapView.overlays]; and it still doesn't work. Any idea how I can remove those overlays?

Thank you.

UPDATE 1

I have the error: malloc: *** error for object 0x5adc0c0: pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug

I think I know why, but don't really know how to fix it... Here is the code when I need to draw another line on my mapView:

// Create a c array of points. 
MKMapPoint *pointsArray = malloc(sizeof(CLLocationCoordinate2D) * 2);

// Create 2 points.
MKMapPoint startPoint = MKMapPointForCoordinate(CLLocationCoordinate2DMake(oldLatitude, oldLongitude));
MKMapPoint endPoint = MKMapPointForCoordinate(CLLocationCoordinate2DMake(newLatitude, newLongitude));

// Fill the array.
pointsArray[0] = startPoint;
pointsArray[1] = endPoint;

// Erase polyline and polyline view if not nil.
if (self.routeLine != nil) {
    [_routeLine release];
    self.routeLine = nil;
}

if (self.routeLineView != nil) {
    [_routeLineView release];
    self.routeLineView = nil;
}

// Create the polyline based on the array of points.
self.routeLine = [MKPolyline polylineWithPoints:pointsArray count:2];

// Add overlay to map.
[self.mapView addOverlay:self.routeLine];

// clear the memory allocated earlier for the points.
free(pointsArray);

// Save old coordinates.
oldLatitude = newLatitude;
oldLongitude = newLongitude;

So I release the routeLine object which is the previous overlay. So when I tried to remove it, it crashes because it has already been deallocated.

Here is the code for the mapView delegate for adding overlay views:

- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
    MKOverlayView* overlayView = nil;

    if(overlay == _routeLine) {
        // If we have not yet created an overlay view for this overlay, create it now. 
        if(self.routeLineView == nil) {
            self.routeLineView = [[[MKPolylineView alloc] initWithPolyline:_routeLine] autorelease];

            self.routeLineView.fillColor = [UIColor blueColor];
            self.routeLineView.strokeColor = [UIColor blueColor];

            // Size of the trace.
            self.routeLineView.lineWidth = routeLineWidth;
        }

        overlayView = self.routeLineView;
    }

    return overlayView;
}

If you guys know how I can fix this issue, removing all overlays from my MKMapView it would be awesome!

UPDATE 2

I tried not releasing my routeLine and routeLineView objects and it works now. It seems like there are no leaks too. So now I'm doing this:

// Erase polyline and polyline view if not nil.
if (self.routeLine != nil) {
    //[_routeLine release];
    self.routeLine = nil;
}

if (self.routeLineView != nil) {
    //[_routeLineView release];
    self.routeLineView = nil;
}
Ancalin answered 16/6, 2011 at 16:25 Comment(0)
S
11

When you call removeOverlays:, the map view will release the MKOverlay and MKOverlayView objects.

You hold your own references to these in _routeLine and _routeLineView.

After removeOverlays: is called, your variables will be pointing to already-released memory. When you re-create the polyline, you are over-releasing which then results in a crash.

So remove the release calls:

if (_routeLine != nil) {
    [_routeLine release];  // <-- remove this
    self.routeLine = nil;
}

if (_routeLineView != nil) {
    [_routeLineView release];  // <-- remove this
    self.routeLineView = nil;
}
Sayers answered 16/6, 2011 at 18:18 Comment(1)
That's what I did :) Thanks a lot @Anna Karenina!Ancalin
B
7

When you step through the code in the debugger, where does the error show up?

One thought, you may have an issue with your retain/release cycle for self.routeLine and self.routeLineView. Assuming they are properties with a retain attribute, when you do

self.routeLine = [MKPolyline polylineWithPoints:pointsArray count:2];  

your synthesized accessor is retaining the new MKPolyline object. That object will also have a retain/autorelease pair from the convenience method that created it. When this method gets called again and you call the

if (self.routeLine != nil) {
    [_routeLine release];
    self.routeLine = nil;
}

code, you will end up releasing the variable twice, the first with the explicit [_routeLine release] call and the second with the synthesized accessor on the self.routeLine = nil; call. It will stay in memory, but will crash the app when your autorelease pool is drained.

In most cases, to clear all the overlays on an MKMapView (named mapView in this sample), I'd do something like the following:

for (id<MKOverlay> overlayToRemove in mapView.overlays)
{
   if ([overlayToRemove isKindOfClass:[OverlayClassToRemove class]])
   {
       [mapView removeOverlay:overlayToRemove];
   }
}
Benedictus answered 16/6, 2011 at 17:28 Comment(5)
The polylineWithPoints:count: method takes a C array of MKMapPoint structs.Sayers
I like the way to remove the overlays you told me, and thought it would work, or at least not crash the app. But it did and I have the same error. @Anna Karenina The way I store the points is right then? I tried to store in a NSArray and can't even add this type of object in it anyway.Ancalin
@Ancalin and @Anna Karenina I stand corrected. That's what I get for guessing about things I haven't done myself. I'll edit my answer.Benedictus
I did remove the [_routeLine release]; and [_routeLineView release]; and it works now. Please look at UPDATE 2 and let me know if you think if there is something wrong.Ancalin
@Ancalin Makes sense. Sorry I didn't finish my edit before you figured that out :)Benedictus
B
1

Swift 3 extenstion

extension MKMapView
{
    func removeAllOverlay(){
        for overlay:MKOverlay in self.overlays  {
            self.remove(overlay)
        }
    }

}
Bartolome answered 6/4, 2017 at 13:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.