'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?
Solution 1:[1]
OK, here's my own solution.
Implement the
MKMapViewDelegate
methodmapViewDidFinishRenderingMap(_ mapView:, fullyRendered:)
. Be sure to use this method instead ofmapViewDidFinishLoadingMap(_ mapView:)
!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)
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.
Solution 2:[2]
Can you tell what do you want to achieve by hiding? if your image is not visible the map won't load data and thats why its delegate is not called as also mentioned on the apple doc see the description below. it says it will be called when current request have been loaded in your case i think map is not visible so its request is not loaded and when you make it visible then the request is loaded and hence you can see that.
This method is called when the map tiles associated with the current request have been loaded. Map tiles are requested when a new visible area is scrolled into view and tiles are not already available. Map tiles may also be requested for portions of the map that are not currently visible. For example, the map view may load tiles immediately surrounding the currently visible area as needed to handle small pans by the user.
https://developer.apple.com/reference/mapkit/mkmapviewdelegate/1452291-mapviewdidfinishloadingmap
Solution 3:[3]
Apparently, MKMapView
only loads the visible tiles of the map, so the mapView
that you want to render offline must be „visible“.
As far as I know, a view is „visible“, if its window
property is set, i.e. not nil
(see progrmr
's answer here).
Thus a possibility could be to setup an additional UIWindow
that has your mapView
as the root view. In this case, the window
property of your mapView
is set, and I believe the mapView
would load the required tiles, so that it can be rendered, even if the additional UIWindow
is not visible.
This is apparently similarly done by a pageViewController
, see the comment of evanflash
in the link above.
Solution 4:[4]
I had this issue last week, because I embedded the MapView
in a Stackview, so it was automatically reduced when set to hidden
. Maybe not your case but you should check the Size
for you mapView.
Also, before I replaced the StackView with an other, setting alpha
to something near zero -instead of using hidden
-, did help (not checked with zero).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Community |
Solution 3 | Community |
Solution 4 | tontonCD |