I'm attempting to create a custom overlay for MKMapView which varies the colour of the polyline according to certain criteria. However, none of my drawing code works, & I can't for the life of me figure out why. I'm using CoreGPX for trackPoints, but I don't think that's relevant to the problem as the overlay's coordinates are set in the normal way.
The subclasses are -
class FlightOverlay: MKPolyline {
enum Route {
case coordinates([CLLocationCoordinate2D])
case gpx(GPXRoot)
}
var trackPoints: [GPXTrackPoint]?
convenience init?(route: Route) {
switch route {
case .coordinates(let coordinates):
self.init(coordinates: coordinates, count: coordinates.count)
case .gpx(let gpxRoot):
guard let track = gpxRoot.tracks.first, let segment = track.segments.first else {
return nil
}
var trackPoints: [GPXTrackPoint] = []
let coordinates: [CLLocationCoordinate2D] = segment.points.compactMap { (point) -> CLLocationCoordinate2D? in
guard let latitude = point.latitude, let longitude = point.longitude else {
return nil
}
trackPoints.append(point) // this ensures that our trackPoints array & the polyline points have the same number of elements
return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
}
self.init(coordinates: coordinates, count: coordinates.count)
self.trackPoints = trackPoints
}
}
}
class FlightOverlayRenderer: MKPolylineRenderer {
override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
guard let polyline = polyline as? FlightOverlay, let trackPoints = polyline.trackPoints, polyline.pointCount > 1 else {
super.draw(mapRect, zoomScale: zoomScale, in: context)
return
}
context.setLineWidth(lineWidth)
var previousPoint = point(for: polyline.points()[0])
for index in 1..<polyline.pointCount {
let trackPoint = trackPoints[index]
let acceleration: Double
if let accelerationValue = trackPoint.extensions?[.acceleration].text, let accel = Double(accelerationValue) {
acceleration = accel
} else {
acceleration = 0
}
let color = UIColor(red: acceleration * 10, green: 0.5, blue: 0.6, alpha: 1).cgColor
context.setStrokeColor(color)
context.beginPath()
context.move(to: previousPoint)
let point = point(for: polyline.points()[index])
context.addLine(to: point)
context.closePath()
context.drawPath(using: .stroke)
previousPoint = point
}
}
}
Even if I comment out all the stuff which attempts to set colours according to a GPXTrackPoint & just draw a start-to-finish line in bright red, nothing appears. When I directly call super, it works fine with the same coordinates.
Any help much appreciated!
Well, maybe it's a rookie error, but it never occurred to me that I'd need to control the lineWidth as well. Turns out it needs to be adjusted according to the zoomScale - I was drawing the line exactly where it needed to be but it was too thin to be seen. For my case, I do -
which gives me a visually pleasing line thickness for all zoom levels.