如何更新 mapView 上 MKAnnotation 对象的位置?

How do I update the location of an MKAnnotation object on a mapView?

我有以下代码,旨在循环遍历当前苹果地图视图上的所有注释并更新它们的位置坐标。

for existingMarker in self.mapView.annotations {

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

很遗憾,这是不允许的。我被告知 'coordinate' 是一个只能获取的 属性。所以这显然不是我要更新已在 mapView 上绘制的注释的 MKAnnotation 位置的方式。那我该怎么做呢?具体来说,我想这样做并尽快获得带有新坐标的地图 "redraw"。我相信这一定是可能的,因为它看起来像是一个常见的用例。

问题是 annotationsMKAnnotation 的数组。但是这个协议只要求有一个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 }

    ...
}

所以,当遍历定义为MKAnnotationMKMapViewannotations时,它并不知道你的坐标是一个变量还是一个常量,并生成该警告。

但是,假设您的注释是 MKPointAnnotation。在该具体注释类型中,coordinate 变量,而不是常量。所以你可以具体说明类型。例如:

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

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

很明显,如果你自己定义符合MKAnnotation的注解class,显然:

  • 定义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()
    }
}

然后模式与上面相同,除了引用您的 class,例如:

mapView.annotations
    .compactMap { [=14=] as? MyAnnotation }
    .forEach { existingMarker in
        existingMarker.coordinate = CLLocationCoordinate2D(latitude: 12.12121212, longitude: 14.312121121)
}

对于Swift,你只需要将坐标字段设为var,然后在尝试变异时输入MKAnnotation即可:

protocol MutableAnnotation : NSObject, MKAnnotation {
    dynamic var coordinate: CLLocationCoordinate2D { get set }
}

class MyAnnotation : MutableAnnotation {
    dynamic var coordinate: CLLocationCoordinate2D
}

// ...

func updateLocation(_ annotation: MKAnnotation, coordinate: CLLocationCoordinate2D)
{
    guard let mutable = annotation as? MutableAnnotation else { return }
    mutable.coordinate = coordinate
}