How to streamline multiple coordinate poly line entries in MKMapKit

匆匆过客 提交于 2020-04-05 06:35:22

问题


I am trying to add multiple poly lines onto a map using mkmapkit. These poly lines indicate walking zones in my area. The problem is that my code is too bulky for a large amount of walking zones.

At the moment my code only indicates 2 walking routes but for instance if I want to add 100 or 1000 walking routes the code would be massive. I'm sure there is a way I could stream line this code so I could add in multiple walking zones with a lot less code but in not too sure the best way to go about it.

import UIKit
import MapKit

class customPin: NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D
var title: String?
var subtitle: String?

init(pinTitle:String, pinSubTitle:String, location:CLLocationCoordinate2D) {
    self.title = pinTitle
    self.subtitle = pinSubTitle
    self.coordinate = location
}
}

class ViewController: UIViewController, MKMapViewDelegate {

@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    //co-ordinates
    let zone1S = CLLocationCoordinate2D(latitude: 52.100525, longitude: -9.623071)
    let zone1E = CLLocationCoordinate2D(latitude: 52.07241, longitude: -9.575299)

    let zone2S = CLLocationCoordinate2D(latitude: 52.054161, longitude: -9.385031)
    let zone2E = CLLocationCoordinate2D(latitude: 52.081185, longitude: -9.247033)


    //pins
    let zone1PinS = customPin(pinTitle: "Zone 1 Start", pinSubTitle: "", location: zone1S)
    let zone1PinE = customPin(pinTitle: "Zone 1 End", pinSubTitle: "", location: zone1E)
    self.mapView.addAnnotation(zone1PinS)
    self.mapView.addAnnotation(zone1PinE)

    let zone2PinS = customPin(pinTitle: "Zone 2 Start", pinSubTitle: "", location: zone2S)
    let zone2PinE = customPin(pinTitle: "Zone 2 End", pinSubTitle: "", location: zone2E)
    self.mapView.addAnnotation(zone2PinS)
    self.mapView.addAnnotation(zone2PinE)


    let zone1PlacemarkS = MKPlacemark(coordinate: zone1S)
    let zone1PlacemarkE = MKPlacemark(coordinate: zone1E)

    let zone2PlacemarkS = MKPlacemark(coordinate: zone2S)
    let zone2PlacemarkE = MKPlacemark(coordinate: zone2E)


    //add polyline to map
    let directionRequestZone1 = MKDirections.Request()
    directionRequestZone1.source = MKMapItem(placemark: zone1PlacemarkS)
    directionRequestZone1.destination = MKMapItem(placemark: zone1PlacemarkE)

    let directionRequestZone2 = MKDirections.Request()
    directionRequestZone2.source = MKMapItem(placemark: zone2PlacemarkS)
    directionRequestZone2.destination = MKMapItem(placemark: zone2PlacemarkE)


    //type of commute
    directionRequestZone1.transportType = .automobile
     directionRequestZone2.transportType = .automobile


    let directions1 = MKDirections(request: directionRequestZone1)
    directions1.calculate { (response, error) in
        guard let directionResonse = response else {
            if let error = error {
                print("we have error getting directions==\(error.localizedDescription)")
            }
            return
        }

        let route = directionResonse.routes[0]
        self.mapView.addOverlay(route.polyline, level: .aboveRoads)


        let rect = route.polyline.boundingMapRect
        //zooming in on location
       // self.mapView.setRegion(MKCoordinateRegion(rect), animated: true)
    }


    let directions2 = MKDirections(request: directionRequestZone2)
    directions2.calculate { (response, error) in
        guard let directionResonse = response else {
            if let error = error {
                print("we have error getting directions==\(error.localizedDescription)")
            }
            return
        }

        let route2 = directionResonse.routes[0]
        self.mapView.addOverlay(route2.polyline, level: .aboveRoads)


        let rect = route2.polyline.boundingMapRect
        //zooming in on location
       // self.mapView.setRegion(MKCoordinateRegion(rect), animated: true)
    }


    //set delegate for mapview
    self.mapView.delegate = self
}


func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
    let renderer = MKPolylineRenderer(overlay: overlay)
    renderer.strokeColor = UIColor.red
    renderer.lineWidth = 5.0
    return renderer
}
}

This is how it looks:

UPDATE: My attempt to use loops hasn't worked. I seem to have a loop working for dropping the start and end zone pins however it doesn't seem to work for drawing the poly lines.

        struct Location {
        let title: String
        let latitude: Double
        let longitude: Double
    }

    let locationsStart = [
        Location(title: "Start",    latitude: 52.100525, longitude: -9.623071)
    ]

    let locationsEnd = [
        Location(title: "End",    latitude: 52.07241, longitude: -9.575299)
    ]

    for location in locationsStart {
        let annotation = MKPointAnnotation()
        annotation.title = location.title
        annotation.coordinate = CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude)
        mapView.addAnnotation(annotation)

        let directionRequestZone1 = MKDirections.Request()
        let zonePlacemarkS = MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude))
        let directionRequest = MKDirections.Request()
        directionRequest.source = MKMapItem(placemark: zonePlacemarkS)
        directionRequestZone1.transportType = .automobile
    }

    for location in locationsEnd {
        let annotation = MKPointAnnotation()
        annotation.title = location.title
        annotation.coordinate = CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude)
        mapView.addAnnotation(annotation)

        let directionRequestZone1 = MKDirections.Request()
        let zonePlacemarkE = MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude))
        let directionRequest = MKDirections.Request()
        directionRequest.destination = MKMapItem(placemark: zonePlacemarkE)
        directionRequestZone1.transportType = .automobile

        let directions1 = MKDirections(request: directionRequestZone1)
        directions1.calculate { (response, error) in
            guard let directionResonse = response else {
                if let error = error {
                    print("we have error getting directions==\(error.localizedDescription)")
                }
                return
            }

            let route = directionResonse.routes[0]
            self.mapView.addOverlay(route.polyline, level: .aboveRoads)


            let rect = route.polyline.boundingMapRect
        }
    }
           //set delegate for mapview
           self.mapView.delegate = self
}


func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
    let renderer = MKPolylineRenderer(overlay: overlay)
    renderer.strokeColor = UIColor.red
    renderer.lineWidth = 5.0
    return renderer
}

回答1:


I adapted your code as follows:

let zone1S = CLLocationCoordinate2D(latitude: 52.100525, longitude: -9.623071)
let zone1E = CLLocationCoordinate2D(latitude: 52.07241, longitude: -9.575299)
let zone2S = CLLocationCoordinate2D(latitude: 52.054161, longitude: -9.385031)
let zone2E = CLLocationCoordinate2D(latitude: 52.081185, longitude: -9.247033)

let zones = [(start:zone1S, end:zone1E), (start:zone2S, end:zone2E)]
for (i, zone) in zones.enumerated() {
    let pinS = customPin(pinTitle: "Zone \(i+1) Start", pinSubTitle: "", location: zone.start)
    let pinE = customPin(pinTitle: "Zone \(i+1) End", pinSubTitle: "", location: zone.end)
    self.mapView.addAnnotation(pinS)
    self.mapView.addAnnotation(pinE)
    let placeS = MKPlacemark(coordinate: zone.start)
    let placeE = MKPlacemark(coordinate: zone.end)
    let req = MKDirections.Request()
    req.source = MKMapItem(placemark: placeS)
    req.destination = MKMapItem(placemark: placeE)
    req.transportType = .automobile
    let dir = MKDirections(request: req)
    dir.calculate { (response, error) in
        guard let directionResponse = response else {
            if let error = error {
                print("we have error getting directions==\(error.localizedDescription)")
            }
            return
        }
        DispatchQueue.main.async {
            let route = directionResponse.routes[0]
            self.mapView.addOverlay(route.polyline, level: .aboveRoads)
        }
    }
}

Clearly this can be trivially extended to any number of zones. (It may be that we should be using something like a DispatchGroup to prevent the networking calculate calls from piling up too quickly, but the goal was to solve it for two pairs of coordinates and this seems to work fine.)



来源:https://stackoverflow.com/questions/60344285/how-to-streamline-multiple-coordinate-poly-line-entries-in-mkmapkit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!