在iOS7中的MKMapView的快照

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

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

但是,返回的图像是一个黑色矩形,在其上方有一个蓝色的当前位置点。 我尝试过使用mapView的不同子层,但结果总是相同的。

有谁知道如何在iOS7的MKMapView快照?

您可以使用MKMapSnapshotter并从生成的MKMapSnapshot获取image 。 请参阅WWDC 2013会话video的讨论, 将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]; }]; 

话虽如此, renderInContext解决scheme仍然适用于我。 有关于在iOS7的主要队列中只做这些的笔记,但它似乎仍然工作。 但MKMapSnapshotter似乎是更适合iOS7的解决scheme。


如果要在快照中包含一些注释,则必须手动绘制它们(!)。 “透视”video中放置贴图工具包的末尾将对此进行详细讨论。 我不得不说,这是我见过苹果公司build议的最优雅的实现之一。 无论如何,在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]; }]; 

对于MacOS的实现,请参阅video了解更多信息,但技术基本相同(创build图像的机制稍有不同)。

对于Swift 3

这里是我从这篇文章中修改的swift 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 } }