Skip to content

Instantly share code, notes, and snippets.

@andrewgleave
Last active November 4, 2022 15:21
Show Gist options
  • Star 83 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save andrewgleave/915374 to your computer and use it in GitHub Desktop.
Save andrewgleave/915374 to your computer and use it in GitHub Desktop.
Zooms out a MKMapView to enclose all its annotations (inc. current location)
MKMapRect zoomRect = MKMapRectNull;
for (id <MKAnnotation> annotation in mapView.annotations) {
MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0);
if (MKMapRectIsNull(zoomRect)) {
zoomRect = pointRect;
} else {
zoomRect = MKMapRectUnion(zoomRect, pointRect);
}
}
[mapView setVisibleMapRect:zoomRect animated:YES];
@mxcl
Copy link

mxcl commented Apr 9, 2018

This is the easiest way:

map.layoutMargins = UIEdgeInsets(top: 10, right: 10, bottom: 10, left: 10)
map.showAnnotations(map.annotations, animated: true)

It works! I promise.

@SimonJanevski
Copy link

SimonJanevski commented Mar 6, 2019

Thanks for this!
In my particular case, I had annotations and overlays for them, like the user's location blue circle overlay (userLocation.horizontalAccuracy). To fit all the annotations and their overlays, I modified this a bit and got these two extensions.

extension MKMapView {
    func setVisibleMapRectToFitAllAnnotations(animated: Bool = true,
                                              shouldIncludeUserAccuracyRange: Bool = true,
                                              edgePadding: UIEdgeInsets = UIEdgeInsets(top: 35, left: 35, bottom: 35, right: 35)) {
        var mapOverlays = overlays

        if shouldIncludeUserAccuracyRange, let userLocation = userLocation.location {
            let userAccuracyRangeCircle = MKCircle(center: userLocation.coordinate, radius: userLocation.horizontalAccuracy)
            mapOverlays.append(MKOverlayRenderer(overlay: userAccuracyRangeCircle).overlay)
        }

        let zoomRect = MKMapRect(bounding: mapOverlays)
        setVisibleMapRect(zoomRect, edgePadding: edgePadding, animated: animated)
    }
} 

extension MKMapRect {
 init(bounding overlays: [MKOverlay]) {
        self = .null
        overlays.forEach { overlay in
            let rect: MKMapRect = overlay.boundingMapRect
            self = self.union(rect)
        }
    }
}

@anirudhamahale
Copy link

anirudhamahale commented Nov 4, 2019

I just modified SimonJanevski's answer to show all annotations and overlays present on MapView.

extension MKMapView {
  func setVisibleMapRectToFitAllAnnotations(animated: Bool = true,
                                            shouldIncludeUserAccuracyRange: Bool = true,
                                            shouldIncludeOverlays: Bool = true,
                                            edgePadding: UIEdgeInsets = UIEdgeInsets(top: 35, left: 35, bottom: 35, right: 35)) {
    var mapOverlays = overlays
    
    if shouldIncludeUserAccuracyRange, let userLocation = userLocation.location {
      let userAccuracyRangeCircle = MKCircle(center: userLocation.coordinate, radius: userLocation.horizontalAccuracy)
      mapOverlays.append(MKOverlayRenderer(overlay: userAccuracyRangeCircle).overlay)
    }
    
    if shouldIncludeOverlays {
      let annotations = self.annotations.filter { !($0 is MKUserLocation) }
      annotations.forEach { annotation in
        let cirlce = MKCircle(center: annotation.coordinate, radius: 1)
        mapOverlays.append(cirlce)
      }
    }
    
    let zoomRect = MKMapRect(bounding: mapOverlays)
    setVisibleMapRect(zoomRect, edgePadding: edgePadding, animated: animated)
  }
}

extension MKMapRect {
  init(bounding overlays: [MKOverlay]) {
    self = .null
    overlays.forEach { overlay in
      let rect: MKMapRect = overlay.boundingMapRect
      self = self.union(rect)
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment