I have built a custom MKOverlayRenderer in order to build polygons, apply a blend mode, then add them to the map view. In my drawMapRect function, I use an array of CGPoints to build the polygon, and create a path.
However, during runtime nothing shows on my map view. My best guess would be the order of which I create the polygon in my drawMapRect function. Any help or guidance would be greatly appreciated, thanks!
override func drawMapRect(mapRect: MKMapRect, zoomScale: MKZoomScale, inContext context: CGContext) {
super.drawMapRect(mapRect, zoomScale: zoomScale, inContext: context)
CGContextSaveGState(context)
CGContextSetBlendMode(context, CGBlendMode.Exclusion)
CGContextSetFillColorWithColor(context, self.fillColor)
CGContextSetStrokeColorWithColor(context, UIColor.whiteColor().CGColor)
CGContextSetLineWidth(context, 1.0)
let point = MKMapPointForCoordinate(self.polygon.points[0])
CGContextMoveToPoint(context, CGFloat(point.x), CGFloat(point.y))
for i in 1..<self.polygon.points.count {
let point = polygon.points[i]
let p = MKMapPointForCoordinate(point)
CGContextAddLineToPoint(context, CGFloat(p.x), CGFloat(p.y))
}
CGContextClosePath(context)
CGContextDrawPath(context, CGPathDrawingMode.FillStroke)
CGContextRestoreGState(context)
}
Here is where my custom overlay renderer is initialized:
func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
if (overlay is MKPolygon) {
let polygonRenderer = MyCustomMapRenderer(overlay: overlay, fillColor: self.polyFactory!.getPolygonColor().CGColor, polygon: self.currentPolygon!)
return polygonRenderer
}
return MKOverlayRenderer()
}
A few observations:
You are taking
points
, which is already an array ofMKMapPoint
(inMKPolygonRenderer
, at least) and callingMKMapPointForCoordinate
. If you want to useMKMapPointForCoordinate
, you'd pass itcoordinates
, notpoints
. Maybe you've defined your own properties, but I might change the name of the property to avoid confusion.You need to convert map points to screen points with
pointForMapPoint
.Also, you are calling
CGContextSetFillColorWithColor
, but passing itfillColor
. But assuming your class is a subclass ofMKPolygonRenderer
, thefillColor
is aUIColor
, not aCGColor
.You seem to be accessing some property,
points
, but theMKPolygonRenderer
doesn't havepoints
property, but ratherpoints()
method.With all of that said, I'm unclear how your code even compiled. I suspect you didn't subclass from
MKPolygonRenderer
, but rather subclassedMKOverlayRenderer
and then implemented a bunch of properties yourself? If you subclassMKPolygonRender
, you get all the polygon behavior for free and only have to implementdrawMapRect
:By the way, we probably could be more sophisticated here (checking to see if the points were visible, figuring out what points to render given the scale ... i.e. if polygon with thousands of points and being scaled into a 100x100 portion of the view, perhaps you don't have to render all of the points, etc.). See WWDC 2010 Customizing Maps with Overlays, which, while dated, is still relevant.
As an aside, your
rendererForOverlay
is curious, too. You are calling some custom initialization method (which is fine), but you're passingoverlay
andcurrentPolygon
. But theoverlay
is the polygon, so I don't know what thiscurrentPolygon
is. AndrendererForOverlay
is stateless, so I'd discourage you from referencing some property, but rather just take theoverlay
that was passed to the method. That way, you could have multiple polygons and let map view keep track of which is which. So I'd do something like:Rob's answer in Swift 3