How to drag an annotation with MKMapView being dragged? (iOS)
Asked Answered
O

3

6

I have a UIViewController that contains a MKMapView. I have added an annotation at my current location by the following code:

import UIKit
import MapKit
class LocationViewController: UIViewController , MKMapViewDelegate ,CLLocationManagerDelegate {
    @IBOutlet weak var mapView: MKMapView!
    var locationManager: CLLocationManager!
    let regionRadius: CLLocationDistance = 1000
    var token: dispatch_once_t = 0
    override func viewDidLoad() {
        super.viewDidLoad()
        mapView.delegate = self
        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.startUpdatingLocation()
    }

func centerMapOnLocation(location: CLLocation) {
    let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate,
        regionRadius * 2.0, regionRadius * 2.0)
    mapView.setRegion(coordinateRegion, animated: true)
}

func mapView(mapView: MKMapView, didUpdateUserLocation userLocation: MKUserLocation) {

    if ((userLocation.coordinate.latitude != 0.0) && (userLocation.coordinate.longitude != 0.0)) {
        dispatch_once(&token) {
            self.centerMapOnLocation(userLocation.location!)
            let annotation = MapPin(title: "This Location", locationName: "Test", discipline: "None", coordinate: userLocation.coordinate)
            mapView.addAnnotation(annotation)
        }
    }
}  

I would like to make the annotation move as the the map view is being moved or dragged by the user. For example my current location is New Albany and if i drag the map not the annotation is will change its stage floating in mid air till i release on top of Pontotoc so the annotation points where i released. I would be grateful for any hits or good tutorials on MapKit.

enter image description here

enter image description here

Orientate answered 17/10, 2015 at 16:1 Comment(0)
E
14

First, you have to return a view for your annotation. You can do so like this:

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
    if annotation is MKUserLocation {
        return nil
    }

    let reuseId = "pin"
    var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
    if pinView == nil {
        pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
        pinView?.draggable = true
    }
    else {
        pinView?.annotation = annotation
    }

    return pinView
}

Then, once you have adopted the MKMapViewDelegate protocol in your controller, you grab the coordinates of a pin after dragging it like this:

func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, didChangeDragState newState: MKAnnotationViewDragState, fromOldState oldState: MKAnnotationViewDragState) {
    if newState == MKAnnotationViewDragState.Ending {
        let droppedAt = view.annotation?.coordinate
        print(droppedAt)
    }
}

See also my sample code.

EDIT

alternative solution:

func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    // Remove all annotations
    self.mapView.removeAnnotations(mapView.annotations)

    // Add new annotation
    let annotation = MKPointAnnotation()
    annotation.coordinate = mapView.centerCoordinate
    annotation.title = "title"
    annotation.subtitle = "subtitle"
    self.mapView.addAnnotation(annotation)
}

Don't forget pinView?.animatesDrop = true in viewForAnnotation.

enter image description here

Enrol answered 18/10, 2015 at 2:39 Comment(1)
I found your sample code helpful. Your code implements a draggable annotation pin where you have to select the pin to drag it. I am trying to implement that the pin is dragged automatically with the map being dragged at the centre of the displaced map.Orientate
G
1

There is another solution. In this post: determine if MKMapView was dragged/moved, the answer with the most votes uses a UIPanGestureRecognizer on the map view. You could use this to move the pin AS you drag the map.

Gilleod answered 1/11, 2016 at 17:31 Comment(0)
C
1

Here is some code that will update the annotation in near-real-time as the user drags or pinches the map:

var mapRegionTimer: Timer?
public func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
    mapRegionTimer?.invalidate()
    mapRegionTimer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true, block: { (t) in
        self.myAnnotation.coordinate = CLLocationCoordinate2DMake(mapView.centerCoordinate.latitude, mapView.centerCoordinate.longitude);
        self.myAnnotation.title = "Current location"
        self.mapView.addAnnotation(self.myAnnotation)
    })
}
public func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    mapRegionTimer?.invalidate()
}
Conflict answered 25/10, 2017 at 12:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.