MapKit:添加MKPolyline隐藏MKTileOverlay

3

我有一个使用MKTileOverlay从本地数据库中显示瓦片的MKMapView工作正常。
然后我使用MKDirections获取两个坐标之间的方向并绘制路线,如下:

MKRoute *route = response.routes.lastObject;
MKPolyline *polyline = route.polyline;

// Draw path on overlay
[self.mapView insertOverlay:polyline aboveOverlay:self.tileOverlay];

但是当我放大查看该线时,它没有瓷砖背景(通常从MKTileOverlay加载(存储在self.tileOverlay中))。 我附加了一张图片以更好地展示。

我还编写了以下代码来渲染覆盖层:

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
    if ([overlay isKindOfClass:[MKTileOverlay class]]) {
        return [[MKTileOverlayRenderer alloc] initWithTileOverlay:overlay];
    }
    else if ([overlay isKindOfClass:[MKPolyline class]]) {
        MKPolylineRenderer *lineView = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
        lineView.strokeColor = [UIColor greenColor];
        lineView.lineWidth = 3;
        return lineView;
    }
    return nil;
}

这就像是“瓷砖”,将线性渲染的“瓷砖”从MKTileOverlay中隐藏起来。我该如何:
- 指定MKPolyline覆盖层必须透明?
- 重新加载背景瓷砖?

截图:

请参见不再具有背景的线条瓷砖 http://sigmanet.ch/tmp/screen.png

2个回答

5

经过几天的努力,这是我自己的解决方案。

扩展 MKPolylineRenderer 并添加一个对 MKTileOverlayRenderer 的引用。我们将这个新类称为 MCPolylineRenderer

在这个类中,重写这两个方法:

- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context {
    // Draw path only if tile render has a tile
    if ([self.tileRenderRef canDrawMapRect:mapRect zoomScale:zoomScale]) {
        [super drawMapRect:mapRect zoomScale:zoomScale inContext:context];
    }
}

- (BOOL)canDrawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale {
    // We can draw path only if tile render can also
    return [self.tileRenderRef canDrawMapRect:mapRect zoomScale:zoomScale];
}

现在,在mapView:renderedForOverlay方法中,替换


MKPolylineRenderer *lineView = [[MKPolylineRenderer alloc] initWithOverlay:overlay]; 

使用

MCPolylineRenderer *lineView = [[MCPolylineRenderer alloc] initWithPolyline:overlay];
lineView.tileRenderRef = self.tileRender;

此外,您需要确保loadTileAtPath:result:方法在没有要渲染的瓦片时不会返回瓦片(例如“未找到瓦片”图像)。
这段代码的作用是当没有背景瓦片可渲染时,路径也不会被绘制。

这个解决方案也适用于ImageRenderer和TileRenderer。非常感谢! - Nadzeya

2
您需要子类化MKPolylineRenderer才能同步渲染器的绘制能力。
import Foundation
import MapKit

class MyPolylineRenderer: MKPolylineRenderer {

    var tileRenderer: MKTileOverlayRenderer?

    override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
        if (tileRenderer?.canDraw(mapRect, zoomScale: zoomScale) ?? true) {
            super.draw(mapRect, zoomScale: zoomScale, in: context)
        }
    }

    override func canDraw(_ mapRect: MKMapRect, zoomScale: MKZoomScale) -> Bool {
        return tileRenderer?.canDraw(mapRect, zoomScale: zoomScale) ?? super.canDraw(mapRect, zoomScale: zoomScale)
    }
}

在您的MKMapViewDelegate中,保留对您的tileRenderer的引用并实现rendererForOverlay

var tileRenderer: MKTileOverlayRenderer?

public func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
    if let polyline = overlay as? MKPolyline {
        let lineRenderer = NXPolylineRenderer(overlay: overlay)
        lineRenderer.tileRenderer = tileRenderer
        // Configure your polyline overlay renderer here...
        return lineRenderer;
    }

    if let tileOverlay = overlay as? MKTileOverlay {
        if tileRenderer == nil || tileRenderer.overlay != overlay {
            tileRenderer = MKTileOverlayRenderer(overlay: overlay)
        }
        return tileRenderer
    }

    return MKOverlayRenderer(overlay: overlay)
}

这个想法全部由@Jonathan提出,我只是为新手发布了一个可以复制/粘贴的Swift代码。


在我的情况下,多边形和折线在瓦片加载后消失了。我该如何解决这个问题? - Anirudha Mahale
@AnirudhaMahale 当您添加折线或多边形时,可以选择其级别(请参见https://developer.apple.com/documentation/mapkit/mkoverlaylevel?language=swift)您还可以调整覆盖层的Z级别(https://developer.apple.com/documentation/mapkit/mkmapview/1452575-exchangeoverlayatindex?changes_6)希望您会在这里找到有用的信息。 - dulgan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接