I'm a programmer specialising in performant and scalable systems using PHP and Ruby and cooking


Published:

Using MKMapSnapshotter with MKPolygon and Swift

Apple showed off a great shiny new API for getting an image of your ma view, but what they left out of their toolset was any elegant way of including annotations or drawn elements along with the map image.

At WWDC 2013 Apple showed a way to add annotations to your map snapshot. I've adapted this a little to draw a 99% acurate representation of a MKPolygon originally added to a MapView.

var snapshotterOptions = MKMapSnapshotOptions()  
snapshotterOptions.region = mapView.region  
snapshotterOptions.scale = UIScreen.mainScreen().scale  
snapshotterOptions.size = mapView.frame.size

var snapshotter = MKMapSnapshotter(options: snapshotterOptions)

snapshotter.startWithCompletionHandler() {  
    snapshot, error in

    var image = snapshot.image

    let finalImageRect = CGRectMake(0, 0, image.size.width, image.size.height)
    let pin = MKPinAnnotationView(annotation: nil, reuseIdentifier: "")
    let pinImage = pin.image

    UIGraphicsBeginImageContextWithOptions(image.size, true, image.scale);

    image.drawAtPoint(CGPointMake(0, 0))

    // draw center/home marker
    var homePoint = snapshot.pointForCoordinate(self.coordinate)
    pinImage.drawAtPoint(homePoint)

    // draw polygon
    var path = UIBezierPath()

    for (i, coordinate) in enumerate(self.areaCoordinates) {
        var point = snapshot.pointForCoordinate(coordinate)

        if (CGRectContainsPoint(finalImageRect, point)) {
            if i == 0 {
                path.moveToPoint(point)
            } else {
                path.addLineToPoint(point)
            }
        }
    }

    path.closePath()

    UIColor.blueColor().colorWithAlphaComponent(0.7).setStroke()
    UIColor.cyanColor().colorWithAlphaComponent(0.2).setFill()

    path.lineWidth = 2.0
    path.stroke()
    path.fill()

    let finalImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    self.snapshotImage = finalImage
}

Now you will have a UIImage of your map and the overlayed polygon.