cocoaprintingmkmapviewmapkitnsprintoperation

How do I print a MKMapView in OS X?


Sending a MKMapView a -print: message results in an output that only contains the +/- buttons and the "legal" link. Same if I try [NSPrintOperation printOperationWithView:someMKMapView] or [theWindowThatContainsAMapView print] or [[NSPrintOperation PDFOperationWithView:someMKMapView insideRect:someMKMapView.bounds toPath:@"foo.pdf" printInfo:nil] runOperation].

Apple's own Maps.app does print the map, btw.

Has anyone managed to print a MKMapView?


Solution

  • The magic class is MKMapSnapshotter

    Assuming there is a MKMapView instance mapView, this is a simple example to create an image of the current content of MKMapView as TIFF file written in Swift. This image is printable.

    let options = MKMapSnapshotOptions()
    options.region = mapView.region;
    options.size = mapView.frame.size;
    
    let fileURL = NSURL(fileURLWithPath:"/path/to/snapshot.tif")
    let mapSnapshotter = MKMapSnapshotter(options: options)
    mapSnapshotter.startWithCompletionHandler { (snapshot, error) -> Void in
      // do error handling
      let image = snapshot.image
      if let data = image.TIFFRepresentation {
        data.writeToURL(fileURL!, atomically:true)
      } else {
        println("could not create TIFF data")
      }
    }
    

    Edit:

    with printing instead of creating a file

    let options = MKMapSnapshotOptions()
    options.region = mapView.region;
    options.size = mapView.frame.size;
    
    let mapSnapshotter = MKMapSnapshotter(options: options)
    mapSnapshotter.startWithCompletionHandler { (snapshot, error) -> Void in
      // do error handling
      let image = snapshot.image
      let imageView = NSImageView()
      imageView.frame = NSRect(origin: NSZeroPoint, size: image.size)
      imageView.image = image
    
      let info = NSPrintInfo.sharedPrintInfo()
      info.horizontalPagination = .FitPagination
      info.verticalPagination = .FitPagination
      let operation = NSPrintOperation(view: imageView, printInfo:info)
      operation.showsPrintPanel = true
      operation.runOperation()