MKTileOverlay:如何重新加载特定的图块或区域
MKTileOverlay: How to reload a specific tile or region
我正在开发一个基于地图的应用程序。我使用 MKTileOverlay
来显示一些动态内容。当新信息到达时,有时某些图块需要重新加载。
我试图在主线程中调用 overlayRenderer.setNeedsDisplayInMapRect(mapRect)
,但显然在我的情况下它不会触发地图重绘。到目前为止,唯一可行的方法是 overlayRenderer.reloadData()
。但是,这将导致重新加载整个内容(而不是仅特定区域)并导致视图闪烁,所以这对我来说不是一个选项。
任何人都可以对此提出任何建议吗?谢谢和干杯。
我终于明白了。事实上,叠加层没有更新并不是因为setNeedsDisplayInMapRect
。经过几次检查后,我发现 setNeedsDisplayInMapRect
实际上导致了 drawMapRect:zoomScale:inContext:
的 运行,但是,默认重绘以某种方式产生了相同的图块图像。我猜这可能是由于 MKTileOverlayRender 的一些内部缓存。
我的解决方案是 class MKTileOverlayRender
,在新的 class 中:
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)
}
我正在开发一个基于地图的应用程序。我使用 MKTileOverlay
来显示一些动态内容。当新信息到达时,有时某些图块需要重新加载。
我试图在主线程中调用 overlayRenderer.setNeedsDisplayInMapRect(mapRect)
,但显然在我的情况下它不会触发地图重绘。到目前为止,唯一可行的方法是 overlayRenderer.reloadData()
。但是,这将导致重新加载整个内容(而不是仅特定区域)并导致视图闪烁,所以这对我来说不是一个选项。
任何人都可以对此提出任何建议吗?谢谢和干杯。
我终于明白了。事实上,叠加层没有更新并不是因为setNeedsDisplayInMapRect
。经过几次检查后,我发现 setNeedsDisplayInMapRect
实际上导致了 drawMapRect:zoomScale:inContext:
的 运行,但是,默认重绘以某种方式产生了相同的图块图像。我猜这可能是由于 MKTileOverlayRender 的一些内部缓存。
我的解决方案是 class MKTileOverlayRender
,在新的 class 中:
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)
}