swiftmkmapviewdraggablemkannotationmkannotationview

Drag Custom Annotation View


I have my CoreData custom Annotation class:

extension Annotation: MKAnnotation {

    public var coordinate: CLLocationCoordinate2D {
        let cllCoordinate = CLLocationCoordinate2D(latitude: self.latitude, longitude: self.longitude)
        return cllCoordinate
    }

    public var title: String? {
        return self.objectId
    }

    class func keyPathsForValuesAffectingCoordinate() -> Set<String> {
        return Set<String>([ #keyPath(latitude), #keyPath(longitude) ])
    }

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Annotation> {
        return NSFetchRequest<Annotation>(entityName: "Annotation")
    }

    @NSManaged public var latitude: Double
    @NSManaged public var longitude: Double
    @NSManaged public var dateTime: Date
    @NSManaged public var type: String
    @NSManaged public var objectId: String?

}

combined with a fetchedResultsController adding and deleting annotations works fine. But now a want to drag an annotation to another position. But only with setting isDraggable to true is not all. I can’t find newer descriptions how this could be integrated.

Here my viewFor method:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {

    guard annotation is Annotation else { return nil }

    let identifier = "Annotation"
    var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)

    if annotationView == nil {
        annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
        annotationView?.isDraggable = true
        annotationView?.canShowCallout = true
    } else {
        annotationView!.annotation = annotation
    }

    let customAnno = annotation as! Annotation
    let image = UIImage(named: customAnno.type)
    annotationView!.image = image

    return annotationView
}

What else do i need? I want to press on the annotation, stay pressed and go to another position, then release the finger and the annotation stays there.


Solution

  • When it drags, it needs to change the coordinate of the underlying annotation. It can’t do that if it’s read-only. So, if you want to make it draggable, you must give the coordinate property a setter:

    public var coordinate: CLLocationCoordinate2D {
        get {
            CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
        }
        set {
            latitude = newValue.latitude
            longitude = newValue.longitude
        }
    }