【问题标题】:How to streamline multiple coordinate poly line entries in MKMapKit如何简化 MKMapKit 中的多个坐标折线条目
【发布时间】:2020-06-06 05:11:01
【问题描述】:

我正在尝试使用 mkmapkit 在地图上添加多条折线。这些折线表示我所在地区的步行区。问题是我的代码对于大量步行区域来说太庞大了。

目前我的代码仅指示 2 条步行路线,但例如,如果我想添加 100 或 1000 条步行路线,则代码将非常庞大。我确信有一种方法可以简化此代码,这样我就可以用更少的代码添加多个步行区域,但不太确定最好的方法。

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
}
}

看起来是这样的:

更新: 我尝试使用循环没有奏效。我似乎有一个循环用于删除开始和结束区域引脚,但它似乎不适用于绘制折线。

        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
}

【问题讨论】:

  • 你知道什么是循环吗?
  • @matt 是的,在这种情况下,我曾尝试让它们正常工作,但我无法正常工作,所以决定询问一下解决问题的最佳方法是什么我的问题是因为我不确定循环是否是最好的方法。
  • 将代码卷入循环的方法是做你正在做的事情:首先只写几个案例。现在想想每次重复的相同点和不同点。不同的是你循环的东西。相同的部分成为循环的主体。在你的情况下,不同的是坐标。其他一切都一样。
  • @matt 我试图尝试使用循环。我想我有用于种植针脚的循环,但由于某种原因,我似乎没有让它用于添加折线。
  • 现在的问题是你有 两个 循环。

标签: ios swift mapkit polyline poly


【解决方案1】:

我将您的代码修改如下:

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)
        }
    }
}

显然,这可以轻松扩展到任意数量的区域。 (可能我们应该使用 DispatchGroup 之类的东西来防止网络 calculate 调用过快堆积,但目标是解决两对坐标的问题,这似乎工作正常。)

【讨论】:

  • 谢谢你,马特,我明白我应该做些什么来实现循环。当我运行你的代码时,它实际上并没有产生折线,它只是产生了引脚。所以你的代码非常接近。
  • 在我的机器上制作的线条,看起来就像你的屏幕截图
  • 当然我只给你看我改变的代码。其他一切都和你一样。
  • 你 100% 正确,错在我这边。欢呼,我真的很感激。我学到了很多。再次感谢。
猜你喜欢
  • 2018-03-08
  • 2021-05-02
  • 2018-09-17
  • 2017-01-26
  • 1970-01-01
  • 2011-07-24
  • 2013-06-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多