正确继承 MKOverlayRenderer

Properly subclassing MKOverlayRenderer

我试图在运行时修改 MKPolyline 的路径以避免它与另一个重叠。

我已经设法得到所有的重叠点,我想做的是在 MKPolylineRenderer 的 func createPath() 中添加一个偏移量来做点,所以 ,理论上,它应该用我添加的小偏移量绘制相同的路径并且它不应该再重叠,但遗憾的是,这没有发生并且折线以相同的方式绘制,就像没有任何改变一样。

我第一次尝试在 addPolyline() 函数之后执行此操作,但我读到一旦您执行此操作,重绘多段线的一种方法是将其删除并再次添加,所以我决定进行测试目的,在添加折线之前完成所有这些操作,以便当我最终将其添加到地图时,它已经有了关于重叠点的信息,但这也没有用。

假设:

1.地图在不同的线程上工作并且因此而没有反映出变化是有原因的。这没关系。优化渲染应该是这样吧

2。完成此操作的正确方法不在 createPath() 函数中。 事实上它不是

  1. 我应该在渲染器的 draw() 函数中应用 transform就是这个

这是 createPath() 函数

override func createPath()
{
   let poly = polyline as! TransportPolyline

   switch poly.id
    {
    case 1:
        let newPath = CGMutablePath()

        for index in 0...poly.pointCount
        {
            let point = poly.points()[index]
            let predicate = { MKMapPointEqualToPoint([=10=], poly.points()[index]) }
            //This is the offset I should apply
            let offset: CGFloat = overlapsAtPoints.contains(predicate) ? 100000.0 : 0.0
            //I tried to use a transform as well, but the result was the same
            var transform = CGAffineTransform(translationX: offset, y: offset)

            if index == 0
            {
                //Here I add the offset and/or the transform without success
                newPath.moveTo(&transform, x: CGFloat(point.x) + offset, y: CGFloat(point.y) + offset)
            }
            else
            {
                //Here as well
                newPath.addLineTo(&transform, x: CGFloat(point.x) + offset, y: CGFloat(point.y) + offset)
            }
        }

        //Set the new path to the Renderer path property
        self.path = newPath
    default: break
    }
}

这是 draw() 函数

override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext)
    {
        let poly = polyline as! TransportPolyline

        guard poly.id == 1 else {
            super.draw(mapRect, zoomScale: zoomScale, in: context)
            return
        }

        //If I apply this the Polyline does move, obviously it move all the Path and not only the segments I want.
        context.translate(x: 1000, y: 1000)

        super.draw(mapRect, zoomScale: zoomScale, in: context)
    }

非常感谢任何建议。

更新:

我发现问题可能在于我如何在 draw 方法中绘制上下文。

文档说:

The default implementation of this method does nothing. Subclasses are expected to override this method and use it to draw the overlay’s contents.

所以通过调用 super.draw() 我没有做任何事情。

关于如何正确覆盖此方法的任何想法?还要考虑到这一点:

To improve drawing performance, the map view may divide your overlay into multiple tiles and render each one on a separate thread. Your implementation of this method must therefore be capable of safely running from multiple threads simultaneously. In addition, you should avoid drawing the entire contents of the overlay each time this method is called. Instead, always take the mapRect parameter into consideration and avoid drawing content outside that rectangle.

所以基本上我在正确的轨道上,但使用了错误的工具。实现这一点的实际方法是覆盖 MKPolylineRenderer 子类中的 draw() 函数。

override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext)
{
   //First validate that the Rect you are asked to draw in actually 
     has some content. See last quote above.
   let theMapRect: MKMapRect = self.overlay.boundingMapRect;

   guard (MKMapRectIntersectsRect(mapRect, theMapRect)) || self.path != nil else {
        return
   }

   //Do some logic if needed.

   //Create and draw your path
   let path = CGMutablePath()
   path.moveTo(nil, x: self.path.currentPoint.x, y: self.path.currentPoint.y)
   path.addLines(nil, between: remainingPoints, count: remainingPoints.count)

   context.addPath(path)

   //Customise it
   context.setStrokeColor(strokeColor!.cgColor)
   context.setLineWidth((lineWidth + CGFloat(0.0)) / zoomScale)

   //And apply it 
   context.strokePath()
}

通过这样做,我能够毫无困难地为每个叠加层成功绘制出我想要的路径。