Как обновить местоположение объекта MKAnnotation на карте?

У меня есть следующий код, который предназначен для перебора всех аннотаций на текущем виде карты Apple и обновления их координат местоположения.

for existingMarker in self.mapView.annotations {

    existingMarker.coordinate.latitude = 12.12121212
    existingMarker.coordinate.longitude = 14.312121121          
}

К сожалению, это не разрешено. Мне сказали, что "координата" - это свойство только для получения. Так что это, очевидно, не то, как я должен обновлять местоположение MKAnnotation аннотаций, уже нарисованных на mapView. Как я могу это сделать тогда? В частности, я хотел бы сделать это и «перерисовать» карту с новыми координатами как можно скорее. Я уверен, что это должно быть возможно, поскольку это похоже на обычный вариант использования.


person sometimesiwritecode    schedule 28.05.2017    source источник


Ответы (1)


Проблема в том, что annotations представляет собой массив MKAnnotation. Но этот протокол требует только наличия свойства coordinate, но не диктует, что это переменная. Обратите внимание на отсутствие set в протоколе:

public protocol MKAnnotation : NSObjectProtocol {

    // Center latitude and longitude of the annotation view.
    // The implementation of this property must be KVO compliant.
    var coordinate: CLLocationCoordinate2D { get }

    ...
}

Таким образом, при переборе annotations из MKMapView, который определен как массив MKAnnotation, он не знает, является ли ваша координата переменной или константой, и генерирует это предупреждение.

Но давайте представим, что ваши аннотации были MKPointAnnotation. В этом конкретном типе аннотации coordinate является переменной, а не константой. Таким образом, вы можете быть конкретным о типе. Например:

for annotation in mapView.annotations {
    if let annotation = annotation as? MKPointAnnotation {
        annotation.coordinate = CLLocationCoordinate2D(latitude: 12.12121212, longitude: 14.312121121)
    }
}

Or

mapView.annotations
    .compactMap { $0 as? MKPointAnnotation }
    .forEach { existingMarker in
        existingMarker.coordinate = CLLocationCoordinate2D(latitude: 12.12121212, longitude: 14.312121121)
}

Очевидно, если вы определите свой собственный класс аннотации, который соответствует MKAnnotation, очевидно:

  • определите coordinate как переменную, а не константу; и

  • убедитесь, что это dynamic.

Таким образом:

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

    // other properties unique to your annotation here

    init(coordinate: CLLocationCoordinate2D, title: String? = nil, subtitle: String? = nil) {
        self.coordinate = coordinate
        self.title = title
        self.subtitle = subtitle

        super.init()
    }
}

И тогда шаблон такой же, как указано выше, за исключением ссылки на ваш класс, например:

mapView.annotations
    .compactMap { $0 as? MyAnnotation }
    .forEach { existingMarker in
        existingMarker.coordinate = CLLocationCoordinate2D(latitude: 12.12121212, longitude: 14.312121121)
}
person Rob    schedule 28.05.2017
comment
К сожалению, в SWIFT 4.0 вы больше не можете этого делать, особенно в отношении динамических координат, выдает мне ошибку Невозможно переопределить с помощью сохраненного свойства «координата» - person JBarros35; 04.10.2019
comment
Обратите внимание, я не создавал подкласс существующего типа аннотации. Я создал свой собственный. Это устраняет проблему «переопределения сохраненного свойства». Но на самом деле вам не нужно определять свой собственный тип, если вы не хотите, вам просто нужно указать конкретный тип, для которого coordinate действительно является переменной. Протокол MKAnnotation требует только существования coordinate, но не того, чтобы это была переменная. Но MKPointAnnotation, например, объявляет его как переменную, так что вы можете использовать его как есть, если хотите. Я обновил свой ответ соответственно. - person Rob; 04.10.2019