Нарисуйте полилинию с помощью Swift

Я пытаюсь понять, как рисовать полилинии с помощью Swift. Я просмотрел документацию, сослался на некоторые учебные пособия и проверил некоторые другие сообщения SO, но я все еще не могу заставить вещь нарисовать линию на моей карте. Вот мой код. Кто-нибудь скажет мне, что я делаю неправильно здесь?

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
    }

}

Спасибо!


person TJ Rogers    schedule 19.12.2014    source источник
comment
Координаты могут быть обратными. Уайт-Плейнс находится на долготе -73.xxx (не широте). Прямо сейчас линия может быть в Антарктиде.   -  person    schedule 19.12.2014
comment
Спасибо Анна! Глупая ошибка. Хотел бы я принять этот комментарий.   -  person TJ Rogers    schedule 19.12.2014


Ответы (3)


Здесь MKGeodesicPolyline решит вашу проблему. Добавьте объект MKGeodesicPolyline вместо MKPolyline.

В вашем коде удалите ниже две строки:

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

И добавьте эти строки:

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

Код цели C:

- (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];
    }];
}

Приведенный выше код Objective C работает отлично, и он покажет наложение ниже:

введите здесь описание изображения

Но если вы попробуете код Swift, этого не будет. Я пытался как мог, чтобы решить это, но это не изменится. Возможно, это ошибка фреймворка MapKit.

person Kampai    schedule 19.12.2014
comment
С кодом OP нет проблем, за исключением того, что координаты обратные. Я не понимаю, какую проблему решит использование геодезической, если координаты изначально неверны. - person ; 19.12.2014
comment
И код ОП, и этот код рисуют линии в Антарктиде. Этот код на самом деле не рисует линию, задуманную OP. - person ; 19.12.2014
comment
В чем разница? - person Kampai; 19.12.2014
comment
Спасибо вам большое за ваш ответ. Это определенно помогло - по крайней мере, теперь у меня есть линия на карте. Но теперь у меня другая проблема. Линия начинается в Уайт-Плейнс, штат Нью-Йорк (мои координаты изменились в соответствии с полезным замечанием Анны), и тянется по дуге через Атлантический океан, заканчиваясь сразу за пределами Африки. Координаты, которые я использовал, должны были нарисовать очень маленькую область в Белых Равнинах. Есть идеи, что здесь происходит? - person TJ Rogers; 19.12.2014
comment
@TJRogers- Да, я видел, что оверлей разбросан, я попробовал его в Objective C, работает отлично. Но не в Swift, я думаю, что это ошибка MapKit. - person Kampai; 22.12.2014
comment
быстрый код получил ошибку.. [здесь] как это исправить: (stackoverflow.com/questions/38271927/) - person Pavlos; 27.03.2017
comment
@PavlosNicolaou: отредактированный ответ для поддержки Swift 3.0 - person Kampai; 27.03.2017

ОБНОВЛЕНИЕ: похоже, это исправлено в Swift 3+. Смотрите принятый ответ.

В этой строке:

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

Вы передаете ссылку на массив Swift как UnsafePointer<CLLocationCoordinate2D>.

Это довольно опасно, и я не уверен, почему Swift позволяет его компилировать. В лучшем случае вы получите нарисованную линию, в худшем случае (что, кажется, в вашем случае) вы не получите ничего.

Конструкторы MKPolyline хотят UsafePointer<CLLocationCoordinate2D>, и это то, что вы должны передать.

Обычно я добавляю частную категорию в MKPolyline, чтобы создать удобный метод инициализации, который принимает обычный массив Swift:

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)
    }
}
person duhanebel    schedule 27.09.2016
comment
Я получаю предупреждение в Xcode 8.3.1: 'initialize(from:)' устарело: оно будет удалено в Swift 4.0. Вместо этого используйте UnsafeMutableBufferPointer.initialize(from:) - person Brandon Nott; 25.04.2017
comment
@BrandonNott На самом деле вам не нужно этого делать. Сделайте свой массив конкретно типа [CLLocationCoordinate2D] и передайте сам массив. Вам не нужно включать & или что-то еще. - person Dallas; 16.08.2017

Создайте полилинию на карте яблока:

import MapKit
import CoreLocation

<CLLocationManagerDelegate,MKMapViewDelegate>

Код

    self.mapView.delegate = self

    var coordinateArray: [CLLocationCoordinate2D] = []
    let destination1 = CLLocationCoordinate2DMake(22.3039, 70.8022)
    let destination2 = CLLocationCoordinate2DMake(23.0225, 72.5714)
    coordinateArray.append(destination1)
    coordinateArray.append(destination2)

    let polygon = MKPolyline(coordinates: coordinateArray, count: coordinateArray.count)
    self.mapView.addOverlay(polygon)

Метод делегирования

func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
    if overlay.isKind(of: MKPolyline.self){
        let polylineRenderer = MKPolylineRenderer(overlay: overlay)
            polylineRenderer.fillColor = UIColor.blue
            polylineRenderer.strokeColor = UIColor.blue
            polylineRenderer.lineWidth = 2
        
        return polylineRenderer
 }
    return MKOverlayRenderer(overlay: overlay)
}
person sohil    schedule 09.09.2020