Ryan
Ryan

Reputation: 21

MapView with Polyline or Annotation losing tile on zoom

I have a MKMapView in an IOS app using cached local tiles that works great. Can zoom, move around, etc...

When, however, I add either annotation or a polyline, it still works great until zoom gets to a certain zoom level, then the tiles under the annotations and polylines don't show up, but all others do fine.

zoomed out at the right level

Zoomed in one two many levels.

If I remove the annotations/lines, the map zooms in correctly and works great for the area the annotations/lines would have been in.

Any ideas?

I reduced this to the smallest test case. This runs fine until you zoom in, then any tiles under the polyline disappear. Zoom out and they re-appear.

import Foundation
import UIKit
import MapKit

class MyController: UIViewController, MKMapViewDelegate {
    @IBOutlet weak var mapView: MKMapView!
    var overlay:MKTileOverlay = MKTileOverlay(URLTemplate: "https://services.arcgisonline.com/ArcGIS/rest/services/USA_Topo_Maps/MapServer/tile/{z}/{y}/{x}.jpg");

override func viewDidLoad() {
    mapView.delegate = self
    mapView.showsUserLocation = true;
    overlay.maximumZ = 15;
    overlay.minimumZ = 12;
    overlay.canReplaceMapContent = true
    mapView.addOverlay(overlay)

    var points: [CLLocationCoordinate2D] = [CLLocationCoordinate2D]()

    points.append(CLLocationCoordinate2D(latitude: 40.7608, longitude: -111.8910));
    points.append(CLLocationCoordinate2D(latitude: 40.8894, longitude: -111.8808));

    var polyline = MKPolyline(coordinates: &points, count: points.count)
    mapView.addOverlay(polyline)
    let region = MKCoordinateRegion(center: points[0], span: MKCoordinateSpan(latitudeDelta:  0.05, longitudeDelta:  0.05))
    mapView.setRegion(region, animated: false)
}


func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
    if overlay is MKPolyline {
        var polylineRenderer = MKPolylineRenderer(overlay: overlay)
        polylineRenderer.strokeColor = UIColor.blueColor()
        polylineRenderer.lineWidth = 5
        return polylineRenderer
    } else if (overlay is MKTileOverlay) {
        let renderr = MKTileOverlayRenderer(overlay: overlay)
        return renderr
    }

    return nil
}
}

Upvotes: 2

Views: 696

Answers (1)

Ron Diel
Ron Diel

Reputation: 1424

I see that it's been three months since you posed this question, but in case it's still of interest I'll share what I've found.

I've added the capability to download map tiles from Apple using an MKMapSnapshotter and store them into a set of tiles directories for use when you're out of cellular service areas, which works pretty well. The directories cover 3 to 6 different zoom levels depending on a user selection, with the tile images arranged in sub-directories under directories named after their zoom levels, per the iOS standard.

When displaying these using an MKTileOverlayRenderer, it switches appropriately among the images for zoom levels between the min and max zoom levels specified in the MKMapRectMake that I used to set up for the MKTileOverlay object.

The map displays all of the tiles appropriately at all of the specified zoom levels, repainting the tiles as sizes change. When the display goes above the max or below the min zoom levels, it continues to display the tiles from either the max or the min zoom levels for a while since it has no tile images for the new sizes. This works OK when there are no polylines, but the system redraws the squares that lie under polylines to resize the lines and when it does so it clears the tile images and looks for the tiles for the new zoom level. Since it doesn't have those tiles, those squares wind up empty on the tiles level, though squares not overlapped by polylines are not cleared and so retain the old images.

BTW, you may have already run into this but in case you haven't, you need to subclass MKTileOverlay so that you can set the location and size of the area mapped by the tiles.

Hope all of this helps explain things, even if it doesn't necessarily solve the problem of what you'll want to do about it.

Upvotes: 1

Related Questions