How can I show polylines of two or more different pins for one destination?
You can define property to keep track of previously added polylines:
var polylines: [MKPolyline]?
Then, when you update directions, remove the old polylines (if any) from the map, update the polylines with the new values, and then add them to the map:
func updateDirections() {
let request = ...
let directions = MKDirections(request: request)
directions.calculate { response, error in
guard let response = response, error == nil else {
print("\(error)")
return
}
if let polylines = self.polylines {
self.mapView.removeOverlays(polylines)
}
self.polylines = response.routes.map { $0.polyline }
self.mapView.addOverlays(self.polylines!)
}
}
Rendering multiple polylines on MapView
The main problem is in the second for
loop:
var fromCoordinateIC :CLLocation =
CLLocation(latitude: icRouteLat[j],
longitude: icRouteLat[j]) //<-- should be icRouteLong
var toCoordinateIC :CLLocation =
CLLocation(latitude: icRouteLong[j+1], //<-- should be icRouteLat
longitude: icRouteLong[j+1])
The second line is not visible (or not where you expect) because it is getting the wrong coordinates.
There are, however, some additional things (not causing or related to the main issue) I'd like to point out:
In the
rendererForOverlay
delegate method, the code is using the outside variableroutePointer
to set the color of the line. This is not recommended. You must not assume when or how often a delegate method will be called. There is no guarantee the delegate method will be called immediately after doingaddOverlay
. It's also possible for the delegate method to be called multiple times for the same overlay.For this reason, you must use data directly associated with the incoming
overlay
object to set the renderer's properties. In the current example, a better alternative is to set each polyline'stitle
property to "one" or "second" and eliminate theroutePointer
variable.In the
rendererForOverlay
delegate method, it would be better to first check ifoverlay
is of typeMKPolyline
before treating it like one. You may later want to add other types of overlays such asMKCircle
orMKPolygon
.Currently, the code is creating a separate
MKPolyline
for each line segment in each route. So if route "one" has 10 line segments and route "second" has 15, the code is currently adding 25 overlays. This is not necessary. AnMKPolyline
can draw multiple line segments. It would be much more efficient to add all the coordinates for a route into an array and after the loop, create and add theMKPolyline
. That way, you would only be adding 2 overlays.Example of creating a single overlay for each route instead of creating multiple overlays for each route (one for each line segment in the route):
//First add all the coordinates to an array...
var coordinates: [CLLocationCoordinate2D] = [CLLocationCoordinate2D]()
for i in 0 ..< routeLat.count
{
var coordinate = CLLocationCoordinate2DMake(routeLat[i], routeLong[i])
coordinates.append(coordinate)
}
//Then create a single overlay with ALL the coordinates in the route...
polyLine = MKPolyline(coordinates: &coordinates, count: coordinates.count);
polyLine.title = "one";
mapView.addOverlay(polyLine);It's not necessary to define separate arrays for latitude and longitude where each array is a list of doubles. It would be much more efficient and will simplify the code significantly to keep a single array of coordinates (of type
CLLocationCoordinate2D
) for each route. AnMKPolyline
can then be created from this array without any looping.Example of using single array of
CLLocationCoordinate2D
s for each route:var routeOneCoordinates = [CLLocationCoordinate2DMake(30.0, -87.0),
CLLocationCoordinate2DMake(32.0, -84.0),
CLLocationCoordinate2DMake(31.5, -83.5),
CLLocationCoordinate2DMake(31.0, -83.0),
CLLocationCoordinate2DMake(33.5, -82.0)]
polyLine = MKPolyline(coordinates: &routeOneCoordinates, count: routeOneCoordinates.count);
polyLine.title = "one";
mapView.addOverlay(polyLine);
MapKit - Change the Color/Stroke of a MKPolyline
I don't think this is the best solution but I found a way of doing this without removing/adding the overlay.
I keep a reference to the let polyLineRenderer = MKPolylineRenderer(overlay: polyLine)
this way on my randomMethod()
I can change the properties I need (stroke, lineWidth) and then just execute setNeedsDisplay()
on the renderer for that polyline.
Is this worst than the other approach?
It may be.. I have to add a structure to store the renderers, but is the only way I found...
Related Topics
Are Static Classes Supported by Swift
Swiftui - Pass Data to Different Views
Build Realm for Swift 3 & Xcode 8
Memory Problems When Switching Between Scenes Spritekit
How to Check If Airpods Are Connected to Iphone
How to Access Cfdictionary in Swift 3
Xcode Takes Long Time to Print Debug Results
Firebase Sms Verification on iOS - 'Token Mismatch'
Passing and Storing Closures/Callbacks in Swift
Uicollectionview Autosize and Dynamic Number of Rows
Swift Protocol with Associated Type - Type May Not Reference Itself as a Requirement
Subclass Uiscrollview in Swift for Touches Began & Touches Moved
How to Change Default Background Color of Callout Bubble with Detailcalloutaccessoryview
Swift: Animate Object Along Animating Path