Swift 3 Add custom annotation pin to MKMapSnapShotter snapshot

痴心易碎 提交于 2019-11-30 13:57:56

To render a MKMapSnapshot with annotation views, you have to manually draw the snapshot's image and the annotation view's image on a new graphic context, and get a new image from that context. In Swift 3:

let rect = imageView.bounds

let snapshot = MKMapSnapshotter(options: options)
snapshot.start { snapshot, error in
    guard let snapshot = snapshot, error == nil else {
        print(error ?? "Unknown error")
        return
    }

    let image = UIGraphicsImageRenderer(size: options.size).image { _ in
        snapshot.image.draw(at: .zero)

        let pinView = MKPinAnnotationView(annotation: nil, reuseIdentifier: nil)
        let pinImage = pinView.image

        var point = snapshot.point(for: location.coordinate)

        if rect.contains(point) {
            point.x -= pinView.bounds.width / 2
            point.y -= pinView.bounds.height / 2
            point.x += pinView.centerOffset.x
            point.y += pinView.centerOffset.y
            pinImage?.draw(at: point)
        }
    }

    // do whatever you want with this image, e.g.

    DispatchQueue.main.async {
        imageView.image = image
    }
}

This was adapted from https://stackoverflow.com/a/18776723/1271826, which itself was adapted from WWDC 2013 video Putting MapKit in Perspective.

Here is an example of a snapshot with a .satelliteFlyover:

I was getting an error from Rob's code that defines "rect" because my MKMapSnapshotter image is a UIImage. However .bounds is a property of UIImageView and not UIImage. So the rect definition throws an error.

Here is how I configured the options:

        let mapSnapshotOptions = MKMapSnapshotOptions()

        // Set the region of the map that is rendered.
        let needleLocation = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
        let region = MKCoordinateRegionMakeWithDistance(needleLocation, 1000, 1000)
        mapSnapshotOptions.region = region

        // Set the scale of the image. We'll just use the scale of the current device, which is 2x scale on Retina screens.
        mapSnapshotOptions.scale = UIScreen.main.scale

        // Set the size of the image output.
        mapSnapshotOptions.size = CGSize(width: 300, height: 300)

        // Show buildings and Points of Interest on the snapshot
        mapSnapshotOptions.showsBuildings = true
        mapSnapshotOptions.showsPointsOfInterest = false

So is there another way to access the .bounds property? Or have I created my snapshot incorrectly?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!