Polylines are disappearing when zoom closely - ios

I created seven different polylines. However some of them are disappearing when I zoom in closely. Why it is happening? How can I prevent this?
Here is my polyline renderer:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(polyline: overlay as! MKPolyline)
renderer.strokeColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.9)
renderer.lineWidth = 2.2
return renderer
}
//Thousands of parameters sending as a parameter
func createPathWithPoints(_ points: [MKMapPoint]) {
let arc = MKPolyline(points: points, count: points.count)
mapView.addOverlay(arc)
}
Please help!

I had similar problem with using MKPolyline and below is what I did to fix this.
1) Make sure that you have your mapView delegate in viewDidLoad().
mapView.delegate = self
2) Add your overlay to the map.
mapView.addOverlay(polyLine())
I am using coredata in my project, so if myLocations are empty then I return empty MKPolyline()
private func polyLine() -> MKPolyline {
guard let locations = myLocations else {
return MKPolyline()
}
// Coordinates
let coords: [CLLocationCoordinate2D] = locations.map { location in
let location = location as! Location
return CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude)
}
return MKPolyline(coordinates: coords, count: coords.count)
}
3) We have access to rendererFor from MKMapViewDelegate. You can change color and width for polyline.
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
guard let polyline = overlay as? MKPolyline else {
return MKOverlayRenderer(overlay: overlay)
}
// Setup renderer
let renderer = MKPolylineRenderer(polyline: polyline)
renderer.strokeColor = .systemBlue
renderer.lineWidth = 3
return renderer
}

Related

How do i add dashed polyline in swift 4?

i already have a polyline in Swift4, how can i make the style of it to Dashed/Dotted line ??
let path = GMSMutablePath(path: GMSPath())
for marker in markerList {
bounds = bounds.includingCoordinate(marker.position)
path.add(marker.position)
}
let polyline = GMSPolyline(path: path)
polyline.strokeColor = UIColor(named: "Primary")!
polyline.strokeWidth = 3.0
polyline.geodesic = true
polyline.map = mapView
Like this map
You need to implement func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer delegate method and using renderer.lineDashPhase and renderer.lineDashPattern properties you should be able to achive what you need
code example
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.red
renderer.lineWidth = 4.0
renderer.lineDashPhase = 2
renderer.lineDashPattern = [NSNumber(value: 1),NSNumber(value:5)]
return renderer
}
result

Swift 3 - Line is getting thicker in MKMapView

I am using MKMapView and PolyLine concept to draw a line.But when the line is drawn line is getting thicker when it goes ahead.I want a single line throughout the route.
My code:-
func assigArray() {
if self.lat.count == self.lon.count {
for i in 0 ..< self.lat.count {
let destination = CLLocationCoordinate2DMake(self.lat[i], self.lon[i])
coordinateArray.append(destination)
}
self.mapp()
}
}
func mapp() {
let coords2 = CLLocationCoordinate2D(latitude: lat.last!, longitude: lon.last!)
let testline = MKPolyline(coordinates: coordinateArray, count: coordinateArray.count)
//Add `MKPolyLine` as an overlay.
map.add(testline)
map.delegate = self
map.centerCoordinate = coords2
map.region = MKCoordinateRegion(center: coords2, span: MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02))
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.red
renderer.lineWidth = 2.0
return renderer
}

How can I draw 2 MKPolyline on MKMapView with different strokes/color?

I have a MKMapView where I'm tracking the path of the user(it's a running app), but the requirement is create a line with two colors. One for the center of the stroke, and other for the border of the stroke. For this, I'm implementing the method func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer of the UIViewController class, in order to return the renderer.
I'm using Swift 4
Any ideas?
Thanks in advance.
Ok, I reach the solution while writing the question, so I will tell you the solution.
First, you have to create two classes, that extend the MKPolyline class
fileprivate class ForegroundOverlay: MKPolyline{
}
fileprivate class BackgroundOverlay: MKPolyline{
}
Second, you have to modify the event that is triggered on position update
var positions = [CLLocationCoordinate2D]()
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0] as CLLocation
positions.append(userLocation.coordinate)
print("Nuber of locations \(positions.count)")
print("user latitude = \(userLocation.coordinate.latitude)")
print("user longitude = \(userLocation.coordinate.longitude)")
speedIndicator.text = "Speed: \(userLocation.speed * 3.6). Altitude: \(userLocation.altitude)"
let fPolyLine = BackgroundOverlay(coordinates: positions, count: positions.count)
mapView.addOverlays([fPolyLine], level: MKOverlayLevel.aboveRoads)
let bPolyLine = ForegroundOverlay(coordinates: positions, count: positions.count)
mapView.addOverlays([bPolyLine], level: MKOverlayLevel.aboveRoads)
}
Third, you have to ask if the polyline is one or another class.
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(polyline: overlay as! MKPolyline)
if overlay is ForegroundOverlay {
renderer.strokeColor = UIColor(red: 230/255, green: 230/255, blue: 1, alpha: 0.5)
renderer.lineWidth = 10
} else {
renderer.strokeColor = UIColor(red: 0, green: 0, blue: 1, alpha: 0.5)
renderer.lineWidth = 30
}
return renderer
}
The result will look like this

Polyline won't show up in MapKit

I'm using Xcode 8.3.2 so first I import mapkit. Then I set markers to the map. Then I add the following code to add a polyline to the map but it won't show any.
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
self.mapView.delegate = self
super.viewDidLoad()
let template = "http://tile.openstreetmap.org/{z}/{x}/{y}.png"
let point1 = CLLocationCoordinate2D(latitude: 6.9271, longitude: 79.8612);
let point2 = CLLocationCoordinate2D(latitude: 9.6615, longitude: 80.0255);
let overlay = MKTileOverlay(urlTemplate: template)
overlay.canReplaceMapContent = true
let location = CLLocationCoordinate2DMake(6.878069, 79.892119)
mapView.add(overlay, level: .aboveLabels)
mapView.setRegion(MKCoordinateRegionMakeWithDistance(location, 1100, 1100), animated: true)
let pin = PinAnnotation(title: "Nimbus", subtitle: "Best", coordinate: location)
mapView.addAnnotation(pin)
let points: [CLLocationCoordinate2D]
points = [point1, point2]
let polyline = MKGeodesicPolyline(coordinates: points, count: 3)
mapView.add(polyline)
UIView.animate(withDuration: 1.5, animations: { () -> Void in
let span = MKCoordinateSpanMake(0.01, 0.01)
let region1 = MKCoordinateRegion(center: point1, span: span)
self.mapView.setRegion(region1, animated: true)
})
}
func mapView(_ mapview: MKMapView, rendererFor overlay: MKOverlay) ->MKOverlayRenderer{
if let overlayGeodesic = overlay as? MKGeodesicPolyline
{
let overLayRenderer = MKPolylineRenderer(polyline: overlayGeodesic)
overLayRenderer.lineWidth = 5
overLayRenderer.strokeColor = UIColor.blue
return overLayRenderer
}
return MKOverlayRenderer(overlay: overlay)
}
First you need to add this line, I think you already have added but anyway
self.mapView.delegate = self
After that you need to implement this MKMapViewDelegate method func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer and return the MKOverlayRenderer needed for your current overlay in this case MKPolylineRenderer this is an important part if you don't implement this method then you never will have your polyline rendered
implementation will be something like this
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let overlayGeodesic = overlay as? MKGeodesicPolyline
{
let overLayRenderer = MKPolylineRenderer(polyline: overlayGeodesic)
overLayRenderer.lineWidth = 5
overLayRenderer.strokeColor = UIColor.blue
return overLayRenderer
}
if let overlayTile = overlay as? MKTileOverlay{
let overLayRenderer = MKTileOverlayRenderer(tileOverlay: overlayTile)
return overLayRenderer
}
return MKOverlayRenderer(overlay: overlay)
}
And voila! there is your polyLine rendered

MKPolyline strange rendering related with zooming in MapKit

I have very simple View Controller to demonstrate this strange rendering behavior of MKPolyline. Nothing special just normal api calls.
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var map: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
map.delegate = self
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let p1 = CLLocationCoordinate2D(latitude: 51, longitude: 13)
var coords = [
p1,
CLLocationCoordinate2D(latitude: 51.1, longitude: 13),
CLLocationCoordinate2D(latitude: 51.2, longitude: 13),
CLLocationCoordinate2D(latitude: 51.3, longitude: 13)
]
let polyline = MKPolyline(coordinates: &coords, count: coords.count)
map.addOverlays([polyline], level: .aboveRoads)
let cam = MKMapCamera(lookingAtCenter: p1, fromDistance: 1000, pitch: 45, heading: 0)
map.setCamera(cam, animated: true)
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let r = MKPolylineRenderer(overlay: overlay)
r.strokeColor = UIColor.blue
return r
}
}
The rendering of the polyline is very strange. During zooming and panning You can see some artifacts.
Take a look at pictures below:
Initial Screen
After some panning
After zooming out and zooming in again
How to fix this? I was trying to implement my own renderer but its the same situation. Like overaly is cached and it's not redrawing on time. I'm working on iOS 10, iPhone 6, Simulator from iOS SDK 10 xCode 8.
Swift 3 solution :
Create a subclass of MKPolylineRenderer
class CustomPolyline: MKPolylineRenderer {
override func applyStrokeProperties(to context: CGContext, atZoomScale zoomScale: MKZoomScale) {
super.applyStrokeProperties(to: context, atZoomScale: zoomScale)
UIGraphicsPushContext(context)
if let ctx = UIGraphicsGetCurrentContext() {
ctx.setLineWidth(self.lineWidth)
}
}
}
Then use it in your rendererFor MapKit delegate :
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = CustomPolyline(overlay: overlay)
renderer.strokeColor = UIColor.red
renderer.lineWidth = 100
return renderer
}
Your polylines won't re-render after zooming thus avoiding the artifacts

Resources