Adding a pin annotation to a map view on a long press in swift
Asked Answered
T

4

12

I'm trying to make an iPhone app which requires users to be able to long press on a place on a map view to drop a pin there. Does anybody know how this is done?

The behaviour is observable in apple maps when you long press on the screen. It will drop a pin and present an annotation saying "dropped pin"

Torchbearer answered 16/6, 2015 at 3:38 Comment(0)
C
11

1) Instantiate a UILongPressGestureRecognizer and add it to the MKMapView.

2) When the selector gets called after the user has a long press, call the addAnnotation method in MKMapView with the appropriate title and coordinate.

3) Then make sure you conform to the MKMapViewDelegate and implement viewForAnnotation: which will be called right after you add the annotation and return a MKPinAnnotationView

Carousal answered 16/6, 2015 at 4:14 Comment(3)
with step 2: How am I to find the appropriate coordinate?Torchbearer
convertPoint(_:toCoordinateFromView:) will allow you to convert the CGPoint selected which can be obtained from the UILongPressGestureRecognizer to the actual coordinate in the MKMapViewCarousal
convertPoint must be used on the MKMapView itself, and not a "regular" ViewController.Kiangsu
B
36
  1. add UILongPressGestureRecognizer to your MapView

    var uilgr = UILongPressGestureRecognizer(target: self, action: "addAnnotation:")
    uilgr.minimumPressDuration = 2.0
    
    map.add (uilgr)
    
    //IOS 9
    map.addGestureRecognizer(uilgr) 
    
  2. Add annotation on Long press detect - func:

    func addAnnotation(gestureRecognizer:UIGestureRecognizer){
        if gestureRecognizer.state == UIGestureRecognizerState.Began {
            var touchPoint = gestureRecognizer.locationInView(map)
            var newCoordinates = map.convertPoint(touchPoint, toCoordinateFromView: map)
            let annotation = MKPointAnnotation()
            annotation.coordinate = newCoordinates
    
            CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: newCoordinates.latitude, longitude: newCoordinates.longitude), completionHandler: {(placemarks, error) -> Void in
                if error != nil {
                    println("Reverse geocoder failed with error" + error.localizedDescription)
                    return
                }
    
            if placemarks.count > 0 {
                let pm = placemarks[0] as! CLPlacemark
    
                // not all places have thoroughfare & subThoroughfare so validate those values
                annotation.title = pm.thoroughfare + ", " + pm.subThoroughfare
                annotation.subtitle = pm.subLocality
                self.map.addAnnotation(annotation)
                println(pm)
            }
            else {
                annotation.title = "Unknown Place"
                self.map.addAnnotation(annotation)
                println("Problem with the data received from geocoder")
            }
            places.append(["name":annotation.title,"latitude":"\(newCoordinates.latitude)","longitude":"\(newCoordinates.longitude)"])
        })
    }
    }
    
  3. or you can add annotation without any title:

    func action(gestureRecognizer:UIGestureRecognizer){
        var touchPoint = gestureRecognizer.locationInView(map)
        var newCoordinates = map.convertPoint(touchPoint, toCoordinateFromView: map)
        let annotation = MKPointAnnotation()
        annotation.coordinate = newCoordinates
        map.addAnnotation(annotation)
    }
    
Boutte answered 8/7, 2015 at 21:39 Comment(1)
It seems in iOS 9 the map.add(uilgr) should be map.addGestureRecognizer (uilgr)Kolnick
C
11

1) Instantiate a UILongPressGestureRecognizer and add it to the MKMapView.

2) When the selector gets called after the user has a long press, call the addAnnotation method in MKMapView with the appropriate title and coordinate.

3) Then make sure you conform to the MKMapViewDelegate and implement viewForAnnotation: which will be called right after you add the annotation and return a MKPinAnnotationView

Carousal answered 16/6, 2015 at 4:14 Comment(3)
with step 2: How am I to find the appropriate coordinate?Torchbearer
convertPoint(_:toCoordinateFromView:) will allow you to convert the CGPoint selected which can be obtained from the UILongPressGestureRecognizer to the actual coordinate in the MKMapViewCarousal
convertPoint must be used on the MKMapView itself, and not a "regular" ViewController.Kiangsu
L
7

First declare UIGestureRecognizer in viewDidLoad

let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(addWaypoint(longGesture:)))
mapView.addGestureRecognizer(longGesture)

Second add the function for longPress

@objc func addWaypoint(longGesture: UIGestureRecognizer) {

    let touchPoint = longGesture.location(in: mapView)
    let wayCoords = mapView.convert(touchPoint, toCoordinateFrom: mapView)
    let location = CLLocation(latitude: wayCoords.latitude, longitude: wayCoords.longitude)
    myWaypoints.append(location)

    let wayAnnotation = MKPointAnnotation()
    wayAnnotation.coordinate = wayCoords
    wayAnnotation.title = "waypoint"
    myAnnotations.append(wayAnnotation)
}

I recommend creating the annotations in an array that will serve you later if you want to delete it, like this...

var myAnnotations = [MKPointAnnotation]()

If you have different annotations, you can delete only the annotations you want, for that when you add a new annotation add to the array. To delete only one group of annotations just do the following

for dots in myAnnotations{
    mapView.removeAnnotation(dots)
}

To delete all annotations try

mapView.removeAnnotations(mapView.annotations)

Apologies for the translation....

Lavine answered 17/10, 2017 at 12:33 Comment(1)
You can't append MKPointAnnotation to CLLocation array. Please edit your answer.Fumigate
Z
2

Update Swift3

func action(gestureRecognizer:UIGestureRecognizer){
    let touchPoint = gestureRecognizer.location(in: mapView)
    let newCoordinates = mapView.convert(touchPoint, toCoordinateFrom: mapView)
    let annotation = MKPointAnnotation()
    annotation.coordinate = newCoordinates
    mapView.addAnnotation(annotation)
}
Zymogen answered 16/3, 2017 at 22:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.