draw line between 2 points - no line?!

ok so I have linked up a button to display a line between 2 points, when I tap the button the map zooms into the area between the 2 points SOURCE and DESTINATION, I am expecting to see a thick blue line though.... its not showing?! please help?


Thanks


@IBAction func showRoute(_ sender: Any) {
       
        let sourceLocation = CLLocationCoordinate2D(latitude: Double(venue.rsLat) ?? 0.0, longitude: Double(venue.rsLong) ?? 0.0)
        let destinationLocation = CLLocationCoordinate2D(latitude: (self.manager.location?.coordinate.latitude)!, longitude: (self.manager.location?.coordinate.longitude)!)
        print("Source: \(sourceLocation)")
        print("Source: \(destinationLocation)")
       
        let sourcePlacemark = MKPlacemark(coordinate: sourceLocation, addressDictionary: nil)
        let destinationPlacemark = MKPlacemark(coordinate: destinationLocation, addressDictionary: nil)
       
        let sourceMapItem = MKMapItem(placemark: sourcePlacemark)
        let destinationMapItem = MKMapItem(placemark: destinationPlacemark)
       
        let directionRequest = MKDirectionsRequest()
        directionRequest.source = sourceMapItem
        directionRequest.destination = destinationMapItem
        directionRequest.transportType = .automobile
       
        let directions = MKDirections(request: directionRequest)
       
        directions.calculate {
            (response, error) -> Void in
           
            guard let response = response else {
                if let error = error {
                    print("Error: \(error)")
                }
               
                return
            }
           
            let route = response.routes[0]
            self.mapView.add((route.polyline), level: MKOverlayLevel.aboveRoads)
           
            let rect = route.polyline.boundingMapRect
            self.mapView.setRegion(MKCoordinateRegionForMapRect(rect), animated: true)
        }
       
        func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
            if overlay is MKPolyline {
                var polylineRenderer = MKPolylineRenderer(overlay: overlay)
                polylineRenderer.strokeColor = UIColor.blue
                polylineRenderer.lineWidth = 5
                return polylineRenderer
            }
           
            return nil
        }
       
    }

Replies

Are you sure of the signature of the func(mapView...)


I think it is func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer

Check also if you have to return nil if not MKPolyline

Try also to fill color for polyline.


With all this, I would rewrite your func as :


func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
    if overlay.isKindOfClass(MKPolyline){
                var polylineRenderer = MKPolylineRenderer(overlay: overlay)
                polylineRenderer.fillColor = UIColor.blue
                polylineRenderer.strokeColor = UIColor.blue
                polylineRenderer.lineWidth = 5
     }
        return MKOverlayRenderer(overlay: overlay)
    }

I. also had this problem with bad signature of the renderer. Try this:


func renderer(for overlay: MKOverlay) -> MKOverlayRenderer?

thank you both, I tried the code you provided Claude31! and Swift 3 rewrote it slightly, it still doesn't work?!


func renderer(for overlay: MKOverlay) -> MKOverlayRenderer? {
        if overlay.isKind(of: MKPolyline.self){
            var polylineRenderer = MKPolylineRenderer(overlay: overlay)
            polylineRenderer.fillColor = UIColor.blue
            polylineRenderer.strokeColor = UIColor.blue
            polylineRenderer.lineWidth = 5
        }
        return MKOverlayRenderer(overlay: overlay)
    }

Check if the function is called and if your code that sets the stroke color and line width is executed. I also think that you should have one polylineRenderer and instantiate it only if it is nil.

so far, I have this:


@IBAction func showRoute(_ sender: Any) {
       
        let sourceLocation = CLLocationCoordinate2D(latitude: Double(venue.rsLat) ?? 0.0, longitude: Double(venue.rsLong) ?? 0.0)
        let destinationLocation = CLLocationCoordinate2D(latitude: (self.manager.location?.coordinate.latitude)!, longitude: (self.manager.location?.coordinate.longitude)!)
        print("Source: \(sourceLocation)")
        print("Source: \(destinationLocation)")
       
        let sourcePlacemark = MKPlacemark(coordinate: sourceLocation, addressDictionary: nil)
        let destinationPlacemark = MKPlacemark(coordinate: destinationLocation, addressDictionary: nil)
       
        let sourceMapItem = MKMapItem(placemark: sourcePlacemark)
        let destinationMapItem = MKMapItem(placemark: destinationPlacemark)
       
        let directionRequest = MKDirectionsRequest()
        directionRequest.source = sourceMapItem
        directionRequest.destination = destinationMapItem
        directionRequest.transportType = .automobile
       
        let directions = MKDirections(request: directionRequest)
       
        directions.calculate {
            (response, error) -> Void in
           
            guard let response = response else {
                if let error = error {
                    print("Error: \(error)")
                }
               
                return
            }
           
            let route = response.routes[0]
            self.mapView.add((route.polyline), level: MKOverlayLevel.aboveRoads)
           
            let rect = route.polyline.boundingMapRect
            self.mapView.setRegion(MKCoordinateRegionForMapRect(rect), animated: true)
           
        }
        func renderer(for overlay: MKOverlay) -> MKOverlayRenderer? {
            if overlay.isKind(of: MKPolyline.self){
                var polylineRenderer = MKPolylineRenderer(overlay: overlay)
                polylineRenderer.fillColor = UIColor.blue
                polylineRenderer.strokeColor = UIColor.blue
                polylineRenderer.lineWidth = 5
            }
            return MKOverlayRenderer(overlay: overlay)
        }
       
    }

I believe I am calling the function correctly?!

is anyone else able to help me here please?

Part of the issue is that your code is conditionally creating your MKPolylineRendererOverlay, configuring it, and then just returning a diferent renderer than the one you just created.


  1. func renderer(for overlay: MKOverlay) -> MKOverlayRenderer? {
  2. if overlay.isKind(of: MKPolyline.self){
  3. var polylineRenderer = MKPolylineRenderer(overlay: overlay)
  4. polylineRenderer.fillColor = UIColor.blue
  5. polylineRenderer.strokeColor = UIColor.blue
  6. polylineRenderer.lineWidth = 5
  7. }
  8. return MKOverlayRenderer(overlay: overlay)
  9. }

should be changed to

  1. func renderer(for overlay: MKOverlay) -> MKOverlayRenderer? {
  2. if overlay.isKind(of: MKPolyline.self){
  3. var polylineRenderer = MKPolylineRenderer(overlay: overlay)
  4. polylineRenderer.fillColor = UIColor.blue
  5. polylineRenderer.strokeColor = UIColor.blue
  6. polylineRenderer.lineWidth = 5
  7. return PolylineRenderer
  8. }
  9. return MKOverlayRenderer(overlay: overlay)
  10. }

I am still stuck on this, please help

@IBAction func showRoute(_ sender: Any) {
       
        let sourceLocation = CLLocationCoordinate2D(latitude: Double(venue.rsLat) ?? 0.0, longitude: Double(venue.rsLong) ?? 0.0)
        let destinationLocation = CLLocationCoordinate2D(latitude: (self.manager.location?.coordinate.latitude)!, longitude: (self.manager.location?.coordinate.longitude)!)
        print("Source: \(sourceLocation)")
        print("Source: \(destinationLocation)")
       
        let sourcePlacemark = MKPlacemark(coordinate: sourceLocation, addressDictionary: nil)
        let destinationPlacemark = MKPlacemark(coordinate: destinationLocation, addressDictionary: nil)
       
        let sourceMapItem = MKMapItem(placemark: sourcePlacemark)
        let destinationMapItem = MKMapItem(placemark: destinationPlacemark)
       
        let directionRequest = MKDirectionsRequest()
        directionRequest.source = sourceMapItem
        directionRequest.destination = destinationMapItem
        directionRequest.transportType = .automobile
       
        let directions = MKDirections(request: directionRequest)
       
        directions.calculate {
            (response, error) -> Void in
           
            guard let response = response else {
                if let error = error {
                    print("Error: \(error)")
                }
               
                return
            }
           
            let route = response.routes[0]
            self.mapView.add((route.polyline), level: MKOverlayLevel.aboveRoads)
           
            let rect = route.polyline.boundingMapRect
            self.mapView.setRegion(MKCoordinateRegionForMapRect(rect), animated: true)
            /
           
        }
        let locations = [CLLocation(latitude: self.londonLon, longitude: self.londonLon), CLLocation(latitude: self.latitude, longitude: self.longitude)]
        var coordinates = locations.map({(location: CLLocation) -> CLLocationCoordinate2D in return location.coordinate})
       
        var polyline = MKPolyline(coordinates: &coordinates, count: locations.count)
       
        self.mapView.add(polyline)
       
    }
    func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
       
        if overlay is MKPolyline {
            var polylineRenderer = MKPolylineRenderer(overlay: overlay)
            polylineRenderer.strokeColor = UIColor.blue
            polylineRenderer.lineWidth = 2
            return polylineRenderer
        }
        return nil
    }

FYI, here is code from my recent app. Draws the line properly. polyLineRenderer is property of my view controller. And obviously, you need `mapView.delegate = self`


extension ManageViewController: MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        if polyLineRenderer == nil {
        
            polyLineRenderer = MKPolylineRenderer(overlay: overlay)
            polyLineRenderer?.strokeColor = GeoKitStyleKit.brandBrightRed
            polyLineRenderer?.lineWidth = 2.0
        }
        return polyLineRenderer!
    }
}


It is different from your code, so I think it is worth looking into...

I just tried your code, it still doesn't work?!

It's still not working, I have added in an extension from MireKE

import UIKit
import MapKit
import FirebaseDatabase
import FirebaseAuth
import CoreLocation
class venueDetails: UIViewController, CLLocationManagerDelegate {
    var polyLineRenderer = MKPolylineRenderer()
   
    var ref:FIRDatabaseReference!
    var refHandle: UInt!
    var databaseHandle: FIRDatabaseHandle!
    var venue :Venue!
    var latitude = Double()
    var longitude = Double()
    var londonLat = Double()
    var londonLon = Double()
    /
    /
    let manager = CLLocationManager()
   
   
   
    @IBOutlet var mapView: MKMapView!
    @IBOutlet var pubName: UILabel!
    @IBOutlet var postCode: UILabel!
    @IBOutlet var telephone: UILabel!
    @IBOutlet var venueImage: UIImageView!
    @IBOutlet var venueImage1: UIImageView!
   
   
    override func viewDidLoad() {
        super.viewDidLoad()
        manager.delegate = self
        manager.desiredAccuracy = kCLLocationAccuracyBest
        manager.requestWhenInUseAuthorization()
        manager.startUpdatingLocation()
        let londonLat = self.manager.location?.coordinate.latitude
        let londonLon = self.manager.location?.coordinate.longitude
        /
        /
        let distancespan:CLLocationDegrees = 5000
        let worthingLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(londonLat!, londonLon!)
        mapView.setRegion(MKCoordinateRegionMakeWithDistance(worthingLocation, distancespan, distancespan), animated: true)
        mapView.clipsToBounds = true
        let worthingClassPin = mapAnnotation(title: "My Location", subtitle: "Here I am!", coordinate: worthingLocation, pinTintColor: UIColor.brown)
       
        /
       
        mapView.addAnnotation(worthingClassPin)
       
        self.pubName.text = venue.rsPubName
        self.postCode.text = venue.rsPostCode
        self.telephone.text = venue.rsTel
       
        let theImageURL = venue.rsImageURL
        let theImageURL1 = venue.rsImageURL
       
       
        let latName = venue.rsLat as? String
        let lonName = venue.rsLong as? String
            let latitude = Double(latName!) ?? 0.0
            let longitude = Double(lonName!) ?? 0.0
           
            let theTitle = venue.rsPubName
            let subTitle = venue.rsTel
            let thepostCode = venue.rsPostCode
           
           
            let distancespan1:CLLocationDegrees = 5000
            let theLocations:CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude, longitude)
            self.mapView.setRegion(MKCoordinateRegionMakeWithDistance(theLocations, distancespan1, distancespan), animated: true)
           
            /
            let worthingClassPin1 = mapAnnotation(title: theTitle!, subtitle: subTitle!, coordinate: theLocations, pinTintColor: UIColor.purple)
            self.mapView.addAnnotation(worthingClassPin1)
            venueImage.downloadedFrom(link: theImageURL!)
        venueImage1.downloadedFrom(link: theImageURL1!)
        /
       
        /
       
    }
   
    @IBAction func showRoute(_ sender: Any) {
       
        let sourceLocation = CLLocationCoordinate2D(latitude: Double(venue.rsLat) ?? 0.0, longitude: Double(venue.rsLong) ?? 0.0)
        let destinationLocation = CLLocationCoordinate2D(latitude: (self.manager.location?.coordinate.latitude)!, longitude: (self.manager.location?.coordinate.longitude)!)
        print("Source: \(sourceLocation)")
        print("Source: \(destinationLocation)")
       
        let sourcePlacemark = MKPlacemark(coordinate: sourceLocation, addressDictionary: nil)
        let destinationPlacemark = MKPlacemark(coordinate: destinationLocation, addressDictionary: nil)
       
        let sourceMapItem = MKMapItem(placemark: sourcePlacemark)
        let destinationMapItem = MKMapItem(placemark: destinationPlacemark)
       
        let directionRequest = MKDirectionsRequest()
        directionRequest.source = sourceMapItem
        directionRequest.destination = destinationMapItem
        directionRequest.transportType = .automobile
       
        let directions = MKDirections(request: directionRequest)
       
        directions.calculate {
            (response, error) -> Void in
           
            guard let response = response else {
                if let error = error {
                    print("Error: \(error)")
                }
               
                return
            }
           
            let route = response.routes[0]
            self.mapView.add((route.polyline), level: MKOverlayLevel.aboveRoads)
           
            let rect = route.polyline.boundingMapRect
            self.mapView.setRegion(MKCoordinateRegionForMapRect(rect), animated: true)
            /
           
        }
       
    }
}
extension UIImageView {
    func downloadedFrom(url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) {
        contentMode = mode
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            guard
                let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
                let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
                let data = data, error == nil,
                let image = UIImage(data: data)
                else { return }
            DispatchQueue.main.async() { () -> Void in
                self.image = image
            }
            }.resume()
    }
    func downloadedFrom(link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) {
        guard let url = URL(string: link) else { return }
        downloadedFrom(url: url, contentMode: mode)
    }
}
extension venueDetails: MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        if polyLineRenderer == nil {
           
            polyLineRenderer = MKPolylineRenderer(overlay: overlay)
           
            polyLineRenderer.strokeColor = UIColor.blue
            polyLineRenderer.lineWidth = 2.0
        }
        return polyLineRenderer
       
    }
}


Please help