Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Render MKMapView offscreen

I'm trying to render an MKMapView into an UIImage, without showing it on the screen. I init the map:

let mapView = MKMapView(frame: CGRect(x: 0, y: 0, width: 1000, height: 1000))
mapView.delegate = self

let region = MKCoordinateRegionMakeWithDistance(location.coordinate(), 1000, 1000)
mapView.setRegion(region, animated: false)

I also implemented the MKMapKitDelegate's method mapViewDidFinishLoadingMap(). This method never gets called, unless I add the map to the view hierarchy and make it visible. This means that setting its alpha to 0, or isHidden to true doesn't work (the map doesn't get loaded in this case). Help?

like image 978
TotoroTotoro Avatar asked Apr 06 '17 03:04

TotoroTotoro


1 Answers

OK, here's my own solution.

  1. Implement the MKMapViewDelegate method mapViewDidFinishRenderingMap(_ mapView:, fullyRendered:). Be sure to use this method instead of mapViewDidFinishLoadingMap(_ mapView:)!

  2. Here's the wacky part. Add your map view to an existing and visible view (I used the view controller's own view), and position it offscreen, with only one pixel showing. This is important, since if the map has no visible pixels, it won't render. E.g.:

    let width = 1000
    let height = 1000
    
    let mapView = MKMapView(frame: CGRect(x: -width+1, y: -height+1, width: width, height: height))
    view.addSubview(mapView)
    
  3. There is no step 3. If you configure the map correctly, the delegate method mentioned in (1) will get called, and at that point you'll have your fully rendered map.

like image 103
TotoroTotoro Avatar answered Oct 26 '22 01:10

TotoroTotoro