Just after I have published my latest app project „Muvy“, a very nice tracking app for all outdoor activities, Apple released iOS 16 and Xcode 14.0. With big horror I had to notice that my app was not working properly with the new version of the operating system. All non-Apple maps were covering my tracks so that they were not visible anymore. What a pity. It turns out that Apple changed the behaviour of the quite central method addOverlay
without notice.
The tracks shown on the map are created as MKPolyline
objects, conforming to the MKOverlay
protocol. Custom (non-Apple) maps are also overlays but of type MKTileOverlay
. There are two principal methods to add overlays to the map (of type MKMapView
):
addOverlay(_ overlay: MKOverlay)
andinsertOverlay(_ overlay: MKOverlay, at index: Int)
The first one adds the overlay just on top of the others while with the second you could specify where in the overlay hierarchy you want to add the new one. With the second method you specify that the new overlay may be covered by the following ones in the overlays array. Overlays with higher index numbers may cover those with lower index numbers. At least, that was the situation before iOS 16.
To make sure that the tracks are always visible on the map I always used insertOverlay(_: at index 0)
for adding the map tiles and addOverlay(_)
for adding the polylines of the tracks. But on iOS 16, surprise surprise, addOverlay
is not appending the array of overlays but inserts the overlay just before the tiles overlays. So the tiles overlays are covering all tracks in my app. Too bad.
To be honest there are also variants of the mentioned methods where you can specify the level („above roads“ or „above labels“) of insertion of the overlays. But in my case both types of overlays (tiles and polylines) are inserted in the same level.
Well, is this a bug or a feature? I don’t know. The documentation does not mention this change in behaviour.
Anyhow, the solution is to create my own method of insertion to make sure that the polylines cannot be covered by the map tiles:
1 2 3 4 5 6 7 8 9 10 |
extension MKMapView { func addOverlayOnTop(_ overlay: MKOverlay) { if let last = self.overlays.last { // its not the first overlay self.insertOverlay(overlay, above: last) // make sure to add it above all } else { // its the first one self.addOverlay(overlay) // just add it } } } |
Funny enough using
self.insertOverlay(overlay, at: self.overlays.count)
instead of
self.insertOverlay(overlay, above: last)
does not work. The overlay is still added before (below) the map tiles. „Stranger and stranger“, as Alice would say. I think I’d vote for a bug but with this extension I have a good workaround.
Thank you for sharing this! Looks like a bug that deserves FB. I was not bitten by this by having to use insertOverlay for a long time now. Doesn’t looks like a feature, but a bug.
Indeed, many thanks for finding this out an sharing, it was a great help for my mapping app.