iOS7中MKMapView的快照

Mic*_*ael 41 mapkit mkmapview ios ios7 mkmapsnapshotter

我试图在iOS7应用程序中创建MKMapView的快照,就像之前iOS版本推荐的那样:

- (UIImage*) renderMapViewToImage
{
   UIGraphicsBeginImageContextWithOptions(mapView.frame.size, NO, 0.0);
   [mapView.layer renderInContext:UIGraphicsGetCurrentContext()];
   UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext(); 
   return image;
}
Run Code Online (Sandbox Code Playgroud)

但是,返回的图像是一个黑色矩形,顶部有一个蓝色的当前位置点.我也试过使用mapView的不同子层,但结果总是一样的.

有谁知道如何在iOS7中拍摄MKMapView快照?

Rob*_*Rob 118

您可以使用MKMapSnapshotterimage从结果中获取MKMapSnapshot.请参阅WWDC 2013会话视频的讨论,将Map Kit放入透视图中.

例如:

MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
options.region = self.mapView.region;
options.scale = [UIScreen mainScreen].scale;
options.size = self.mapView.frame.size;

MKMapSnapshotter *snapshotter = [[MKMapSnapshotter alloc] initWithOptions:options];
[snapshotter startWithCompletionHandler:^(MKMapSnapshot *snapshot, NSError *error) {
    UIImage *image = snapshot.image;
    NSData *data = UIImagePNGRepresentation(image);
    [data writeToFile:[self snapshotFilename] atomically:YES];
}];
Run Code Online (Sandbox Code Playgroud)

话虽如此,renderInContext解决方案仍然适用于我.有关于仅在iOS7的主队列中执行此操作的说明,但它似乎仍然有效.但MKMapSnapshotter似乎更适合iOS7的解决方案.


如果要在快照中包含一些注释,则必须手动绘制它们(!).在透视视频中的Putting Map Kit结尾处对此进行了详细讨论.我不得不说这是我见过苹果建议的最不优雅的实现之一.无论如何,在iOS中,它可能看起来像:

MKMapSnapshotOptions *options = [[MKMapSnapshotOptions alloc] init];
options.region = self.mapView.region;
options.scale = [UIScreen mainScreen].scale;
options.size = self.mapView.frame.size;

MKMapSnapshotter *snapshotter = [[MKMapSnapshotter alloc] initWithOptions:options];
[snapshotter startWithQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) completionHandler:^(MKMapSnapshot *snapshot, NSError *error) {

    // get the image associated with the snapshot

    UIImage *image = snapshot.image;

    // Get the size of the final image

    CGRect finalImageRect = CGRectMake(0, 0, image.size.width, image.size.height);

    // Get a standard annotation view pin. Clearly, Apple assumes that we'll only want to draw standard annotation pins!

    MKAnnotationView *pin = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:@""];
    UIImage *pinImage = pin.image;

    // ok, let's start to create our final image

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

    // first, draw the image from the snapshotter

    [image drawAtPoint:CGPointMake(0, 0)];

    // now, let's iterate through the annotations and draw them, too

    for (id<MKAnnotation>annotation in self.mapView.annotations)
    {
        CGPoint point = [snapshot pointForCoordinate:annotation.coordinate];
        if (CGRectContainsPoint(finalImageRect, point)) // this is too conservative, but you get the idea
        {
            CGPoint pinCenterOffset = pin.centerOffset;
            point.x -= pin.bounds.size.width / 2.0;
            point.y -= pin.bounds.size.height / 2.0;
            point.x += pinCenterOffset.x;
            point.y += pinCenterOffset.y;

            [pinImage drawAtPoint:point];
        }
    }

    // grab the final image

    UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    // and save it

    NSData *data = UIImagePNGRepresentation(finalImage);
    [data writeToFile:[self snapshotFilename] atomically:YES];
}];
Run Code Online (Sandbox Code Playgroud)

对于MacOS实现,请参阅该视频以获取更多信息,但技术基本相同(创建图像的机制略有不同).

  • 很棒的答案!直到Apple的视频结束我都没有,我不能同意:这根本不是优雅的.这个很酷的新API的整个想法是不依赖于Image Context渲染和使用MapKit附加API.但它有效,看起来像一个魅力.这是一个screeshot:https://dl.dropboxusercontent.com/u/2452151/Permalink/EpicList_iPhone_App_Screenshot232.png (3认同)

Rat*_*ain 7

对于iOS 10 及更高版本,您可以使用UIGraphicsImageRendererclass 将任何视图渲染为图像(以防万一,如果您不想使用MKMapSnapshotter,因为我正在使用MapBox)。

let render = UIGraphicsImageRenderer(size: self.mapView.bounds.size)
let image = render.image { ctx in
  self.mapView.drawHierarchy(in: self.mapView.bounds, afterScreenUpdates: true)
}
Run Code Online (Sandbox Code Playgroud)

结果

在此处输入图片说明


use*_*289 5

对于Swift 3

这是我根据本文修改的快速3版本: 使用MapKit将地图渲染为图像

以下代码允许您基于Point(1坐标)和Polyline(多个坐标)来对区域进行快照

func takeSnapShot() {
    let mapSnapshotOptions = MKMapSnapshotOptions()

    // Set the region of the map that is rendered. (by one specified coordinate)
    // let location = CLLocationCoordinate2DMake(24.78423, 121.01836) // Apple HQ
    // let region = MKCoordinateRegionMakeWithDistance(location, 1000, 1000)

    // Set the region of the map that is rendered. (by polyline)
    // var yourCoordinates = [CLLocationCoordinate2D]()  <- initinal this array with your polyline coordinates
    let polyLine = MKPolyline(coordinates: &yourCoordinates, count: yourCoordinates.count)
    let region = MKCoordinateRegionForMapRect(polyLine.boundingMapRect)

    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: IMAGE_VIEW_WIDTH, height: IMAGE_VIEW_HEIGHT)

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

    let snapShotter = MKMapSnapshotter(options: mapSnapshotOptions)

    snapShotter.start() { snapshot, error in
        guard let snapshot = snapshot else {
            return
        }
        self.imageView.image = snapshot.image
    }
}
Run Code Online (Sandbox Code Playgroud)