swiftswift3mkmapviewxcode8uilongpressgesturerecogni

Create long press gesture recognizer with annotation pin


What I did so far was create a map. Then show user location and center it so that map is centered when travelling (car etc)

But now I would like to add a long press gesture so that If a user does the input a pin will be dropped. I have struggled with tutorials and the simulator crashes.

How would I add longPressGesturerecognizer so that it drops a pin on my mapView.

Here is my code-

import UIKit
import MapKit
import CoreLocation

class Page2: UIViewController, MKMapViewDelegate,  CLLocationManagerDelegate{

    @IBOutlet var mapView: MKMapView!
    let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.locationManager.delegate = self
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
        self.locationManager.requestWhenInUseAuthorization()
        self.locationManager.startUpdatingLocation()
        //blue dot on the map
        self.mapView.showsUserLocation = true
        //tracking mode on
        self.mapView.userTrackingMode = .follow
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // location Manager Delegate center user on map
    private func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {

        let location = locations.last
        let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: (location?.coordinate.longitude)!)
        let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.005, longitudeDelta: 0.005)) //zoom on map
        self.mapView.setRegion(region, animated: true)
        self.locationManager.stopUpdatingLocation()
    }

    // print errors
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error){
        print("Errors: " + error.localizedDescription)
    }
}

Solution

  • First of all in Swift 3 signature of CLLocationManagerDelegate method's locationManager(_:didUpdateLocations:) is changed, so you need to change that method as follow.

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
         //your code and don't forgot to remove private
    }
    

    You can use longGesture with mapView like this, first addGestureRecognizer in your mapView in the viewDidLoad.

    let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(addAnnotationOnLongPress(gesture:)))
    longPressGesture.minimumPressDuration = 1.0
    self.mapView.addGestureRecognizer(longPressGesture)
    

    Now add action for that UILongPressGestureRecognizer.

    @objc func addAnnotationOnLongPress(gesture: UILongPressGestureRecognizer) {
    
        if gesture.state == .ended {
            let point = gesture.location(in: self.mapView)
            let coordinate = self.mapView.convert(point, toCoordinateFrom: self.mapView)
            print(coordinate)
            //Now use this coordinate to add annotation on map.
            var annotation = MKPointAnnotation()
            annotation.coordinate = coordinate
            //Set title and subtitle if you want
            annotation.title = "Title" 
            annotation.subtitle = "subtitle" 
            self.mapView.addAnnotation(annotation)
        }
    }