MKTileOverlay:如何重新加载特定的图块或区域

时间:2016-06-28 16:17:50

标签: ios mapkit mktileoverlay

我正在开发一款基于地图的应用。我使用MKTileOverlay来显示一些动态内容。有时某些瓷砖需要在新信息到达时重新加载。

我试图在主线程中调用overlayRenderer.setNeedsDisplayInMapRect(mapRect),但显然它不会触发我的情况下的地图重绘。到目前为止,唯一有效的方法是overlayRenderer.reloadData()。但是,这将导致重新加载整个内容(而不仅仅是特定区域)并导致视图中的闪烁,因此这对我来说不是一个选项。

有人可以就此提出任何建议吗?谢谢&欢呼声。

1 个答案:

答案 0 :(得分:2)

最后我明白了。实际上,叠加层未更新不是由setNeedsDisplayInMapRect引起的。经过多次检查后,我发现setNeedsDisplayInMapRect实际上导致了drawMapRect:zoomScale:inContext:的运行,但是,默认重绘会以某种方式生成相同的图块图像。我想这可能是由于MKTileOverlayRender的一些内部缓存。

我的解决方案是将MKTileOverlayRender和新类继承:

override func canDrawMapRect(mapRect: MKMapRect, zoomScale: MKZoomScale) -> Bool {

    let tilePath = self.tilePathForMapRect(mapRect, andZoomScale: zoomScale)
    let tilePathString = stringForTilePath(tilePath)
    if let _ = self.cache.objectForKey(tilePathString) {
        return true
    } else {
        let tileOverlay = self.overlay as! MKTileOverlay
        tileOverlay.loadTileAtPath(tilePath, result: {
            data, error in
            if error == nil && data != nil {
                if let image = UIImage(data: data!) {
                    self.cache.setObject(image, forKey: tilePathString)
                    self.setNeedsDisplayInMapRect(mapRect, zoomScale: zoomScale)
                }
            }
        })

        return false
    }
}

override func drawMapRect(mapRect: MKMapRect, zoomScale: MKZoomScale, inContext context: CGContext) {
    let tilePath = self.tilePathForMapRect(mapRect, andZoomScale: zoomScale)
    let tilePathString = stringForTilePath(tilePath)

    if let image = self.cache.objectForKey(tilePathString) as? UIImage {
        CGContextDrawImage(context, self.rectForMapRect(mapRect), image.CGImage)
    } else {
        super.setNeedsDisplayInMapRect(mapRect, zoomScale: zoomScale)
    }

    self.cache.removeObjectForKey(tilePathString)
}