Draw polyline using Swift

非 Y 不嫁゛ 提交于 2019-11-29 08:48:58

问题


I'm trying to get an understanding of how to draw polylines using Swift. I've looked at the documentation, referenced some tutorials, and checked out some other SO posts, but I still can't get the thing to draw a line on my map. Here's my code. Anyone tell me what I'm doing wrong here?

import UIKit
import MapKit

class FirstViewController: UIViewController {

    @IBOutlet weak var map: MKMapView!

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)

        let location = CLLocationCoordinate2D(
            latitude: -73.761105,
            longitude: 41.017791
        )

        let span = MKCoordinateSpanMake(0.07, 0.07)
        let region = MKCoordinateRegion(center: location, span: span)
        map.setRegion(region, animated: true)

        let annotation = MKPointAnnotation()
        annotation.setCoordinate(location)
        annotation.title = "White Plains"
        annotation.subtitle = "Westchester County"
        map.addAnnotation(annotation)

        var locations = [CLLocation(latitude: -73.761105, longitude: 41.017791), CLLocation(latitude: -73.760701,longitude: 41.019348), CLLocation(latitude: -73.757201, longitude: 41.019267), CLLocation(latitude: -73.757482, longitude: 41.016375), CLLocation(latitude: -73.761105, longitude: 41.017791)]
        var coordinates = locations.map({(location: CLLocation!) -> CLLocationCoordinate2D in return location.coordinate})
        var polyline = MKPolyline(coordinates: &coordinates, count: locations.count)

        self.map.addOverlay(polyline)

    }

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

        return nil
    }

}

Thanks!


回答1:


Here MKGeodesicPolyline will solve your problem. Add object of MKGeodesicPolyline instead of MKPolyline.

In your code remove below two lines:

    let polyline = MKPolyline(coordinates: &coordinates, count: locations.count)
    map.add(polyline)

And add these lines:

    let geodesic = MKGeodesicPolyline(coordinates: coordinates, count: 2)
    map.addOverlay(geodesic)

Swift 5.0:

func createPolyline(mapView: MKMapView) {
    let point1 = CLLocationCoordinate2DMake(-73.761105, 41.017791);
    let point2 = CLLocationCoordinate2DMake(-73.760701, 41.019348);
    let point3 = CLLocationCoordinate2DMake(-73.757201, 41.019267);
    let point4 = CLLocationCoordinate2DMake(-73.757482, 41.016375);
    let point5 = CLLocationCoordinate2DMake(-73.761105, 41.017791);

    let points: [CLLocationCoordinate2D]
    points = [point1, point2, point3, point4, point5]

    let geodesic = MKGeodesicPolyline(coordinates: points, count: 5)
    map.addOverlay(geodesic)

    UIView.animate(withDuration: 1.5, animations: { () -> Void in
        let span = MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01)
        let region1 = MKCoordinateRegion(center: point1, span: span)
        self.map.setRegion(region1, animated: true)
    })
}

Objective C code:

- (void) createGeoPolyline {

    CLLocationCoordinate2D point1 = { -73.761105, 41.017791 };
    CLLocationCoordinate2D point2 = { -73.760701, 41.019348 };
    CLLocationCoordinate2D point3 = { -73.757201, 41.019267 };
    CLLocationCoordinate2D point4 = { -73.757482, 41.016375 };
    CLLocationCoordinate2D point5 = { -73.761105, 41.017791 };

   CLLocationCoordinate2D points[] = {point1, point2, point3, point4, point5};

    MKGeodesicPolyline *geodesic = [MKGeodesicPolyline polylineWithCoordinates:&points[0] count:5];
    [self.mapView addOverlay:geodesic];

    [UIView animateWithDuration:1.5 animations:^{
        MKCoordinateRegion region;
        region.center = point1;

        MKCoordinateSpan span;
        span.latitudeDelta  = 0.01;
        span.longitudeDelta = 0.01;
        region.span = span;
        [self.mapView setRegion:region animated:YES];
    }];
}

Above Objective C code works perfect and it will show overlay below:

But if you try Swift code it will not. I tried as much as I can to solve it out but It won't change. May be it is bug from MapKit framework.




回答2:


UPDATE: This seems to be fixed on Swift 3+. See accepted answer.

On this line:

var polyline = MKPolyline(coordinates: &coordinates, count: locations.count)

You're casting a Swift array reference as an UnsafePointer<CLLocationCoordinate2D>.

That's pretty dangerous and I'm not sure why Swift allows it to compile. Best case scenario you get the line drawn, worse case (which seems to be your case) you get nothing.

The MKPolyline constructors wants an UsafePointer<CLLocationCoordinate2D> and that's what you should pass.

I usually add a private category to MKPolyline to create a convenience init method that accepts a normal Swift array:

private extension MKPolyline {
    convenience init(coordinates coords: Array<CLLocationCoordinate2D>) {
        let unsafeCoordinates = UnsafeMutablePointer<CLLocationCoordinate2D>.alloc(coords.count)
        unsafeCoordinates.initializeFrom(coords)
        self.init(coordinates: unsafeCoordinates, count: coords.count)
        unsafeCoordinates.dealloc(coords.count)
    }
}


来源:https://stackoverflow.com/questions/27558912/draw-polyline-using-swift

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