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
Related
MKMapView class is added and assigned delegate:
let mapView: MKMapView = {
let map = MKMapView()
map.translatesAutoresizingMaskIntoConstraints = false
return map
}()
override func viewDidLoad() {
self.view.addSubview(mapView)
mapView.delegate = self
let center = mapView.centerCoordinate
NSLayoutConstraint.activate([
mapView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 0),
mapView.leftAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leftAnchor, constant: 0),
mapView.rightAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.rightAnchor, constant: 0),
mapView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: 0)
])
}
Then the mapView is assigned center coordinate and span is set. zoomLevel is set to 1
let span = MKCoordinateSpan(latitudeDelta: 0, longitudeDelta: 360 / pow(2, Double(zoomLevel)) * Double(mapView.frame.size.width) / 256)
setRegion(MKCoordinateRegion(center: coordinate, span: span), animated: animated)
// I wrote URL like this because I was told that MKTileOverlay class will take care of z, x, and y value.
let urlTemplate = "https://tile.openweathermap.org/map/temp_new/{z}/{x}/{y}.png?appid={my API ID}"
// urlTemplate is added to MKTileOverlay
let overlay = MKTileOverlay(urlTemplate: urlTemplate)
overlay.canReplaceMapContent = true
// And just when I am about to add overlay to mapView, the app will crash:
self.mapView.addOverlay(overlay)
// It takes me to AppDelegate.swift and then it shows this message:
Thread 1: Exception: "Expected a MKTileOverlay but got (null)"
Everything was added to viewDidLoad().
I also added renderedFor delegate functions. Like this:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
var renderer = MKTileOverlayRenderer()
print("overlay rendered For: \(overlay)")
if overlay is MKTileOverlay {
renderer = MKTileOverlayRenderer(overlay:overlay)
renderer.alpha = 0.8
}
return renderer
}
I had the same problem and what was causing the crash for me was the initialisation of MKTileOverlayRenderer() without specifying an overlay.
So basically, your code inside the mapView(_:rendererFor:) delegate method should be:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
print("overlay rendered For: \(overlay)")
if let overlay = overlay as? MKTileOverlay {
renderer = MKTileOverlayRenderer(overlay: overlay)
renderer.alpha = 0.8
return renderer.alpha
} else {
return MKOverlayRenderer(overlay: overlay)
}
}
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
}
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
}
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
I'm trying to add a circle overlay to my map. I followed the apple docs and got this far, but the overlay doesn't appear when I run the app. Here's my code...
#IBOutlet var map: MKMapView!
let location = CLLocationCoordinate2DMake(40.73085, -73.99750)
let regionRadius: CLLocationDistance = 5500
func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
let diskRenderer: MKCircleRenderer = MKCircleRenderer.init()
diskRenderer.fillColor = UIColor.init(red: 0, green: 192, blue: 295, alpha: 1)
return diskRenderer
}
override func viewDidLoad() {
super.viewDidLoad()
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location, regionRadius, regionRadius)
map.setRegion(coordinateRegion, animated: true)
let diskOverlay: MKCircle = MKCircle.init(centerCoordinate: location, radius: 5000)
map.addOverlay(diskOverlay)
// Do any additional setup after loading the view.
}
I'm teaching myself all this stuff so forgive me if i've made an obvious mistake.
See the accepted answer to this question:
How to create MKCircle in Swift?
Steps are:
Ensure this controller implements MKMapViewDelegate:
class YourViewController: UIViewController, MKMapViewDelegate
In viewDidLoad set the delegate on map to self:
override func viewDidLoad() {
super.viewDidLoad()
map.delegate = self;`
Add the following function to render the overlay (change the color, etc):
func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
if let overlay = overlay as? MKCircle {
let circleRenderer = MKCircleRenderer(circle: overlay)
circleRenderer.fillColor = UIColor.blueColor()
return circleRenderer
}
else {
return MKOverlayRenderer(overlay: overlay)
}
}
The radius of your circle is too big as it is currently set and the whole map will be blue. Set it to something small, like 1000, so you can see the circle.
objc in a class that is set as a mkmapviewdelegate:
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay
{
if ([overlay isKindOfClass:[MKPolygon class]]) {
MKPolygon *polygon = (MKPolygon *)overlay;
MKPolygonRenderer *renderer = [[MKPolygonRenderer alloc] initWithPolygon:polygon];
renderer.strokeColor = [UIColor blueColor];
renderer.lineWidth = 5.;
return renderer;
}
return [[MKOverlayRenderer alloc] initWithOverlay:overlay];
}