18

I am looking to be able to ask the app user for his/her current location and a pin to be automatically dropped on that location. Here is my code for grabbing the current location, but I am having trouble understanding how I can drop a pin for the current location.

import UIKit
import MapKit
import CoreLocation


class MapVC: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {



@IBOutlet weak var map: MKMapView!

let locationManager =  CLLocationManager()

override func viewDidLoad() {
    super.viewDidLoad()

    // User's location

    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    if #available(iOS 8.0, *) {
        locationManager.requestAlwaysAuthorization()
    } else {
        // Fallback on earlier versions
    }
    locationManager.startUpdatingLocation()

    // add gesture recognizer
    let longPress = UILongPressGestureRecognizer(target: self, action: #selector(MapVC.mapLongPress(_:))) // colon needs to pass through info
    longPress.minimumPressDuration = 1.5 // in seconds
    //add gesture recognition
    map.addGestureRecognizer(longPress)
}

// func called when gesture recognizer detects a long press

func mapLongPress(_ recognizer: UIGestureRecognizer) {

    print("A long press has been detected.")

    let touchedAt = recognizer.location(in: self.map) // adds the location on the view it was pressed
    let touchedAtCoordinate : CLLocationCoordinate2D = map.convert(touchedAt, toCoordinateFrom: self.map) // will get coordinates

    let newPin = MKPointAnnotation()
    newPin.coordinate = touchedAtCoordinate
    map.addAnnotation(newPin)


}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

    let location = locations.last! as CLLocation

    let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
    let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))




    //set region on the map
    self.map.setRegion(region, animated: true)



}

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


}
Kevin
  • 1,189
  • 2
  • 17
  • 44

2 Answers2

26

If you want to add pin to user location you can do that in didUpdateLocations delegate method like this

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    mapView.removeAnnotation(newPin)

    let location = locations.last! as CLLocation

    let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
    let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))        

    //set region on the map
    map.setRegion(region, animated: true)

    newPin.coordinate = location.coordinate
    map.addAnnotation(newPin)

}

Create a global variable for your pin

let newPin = MKPointAnnotation()

So whenever user will move to a new location the previous pin will be removed and a new pin will be added to updated location.

Rajat
  • 10,977
  • 3
  • 38
  • 55
  • When I implement this, it gives me the error "Use of unresolved identifier 'mapView'" – Kevin Nov 30 '16 at 18:23
  • 1
    `mapView` is name of variable of `MapView` replace it with your `MapView` variable which is `map `, also i have updated it in my answer – Rajat Nov 30 '16 at 18:24
  • Ah I see. This has fixed the error. How can I test this out? When I run it with the map it doesn't recognize the app's current location. – Kevin Nov 30 '16 at 18:33
  • First of all you need to add 'NSLocationAlwaysUsageDescription' in your plist, the add breakpoint on didUpdateLocation method and check whether that method being called or not – Rajat Nov 30 '16 at 18:38
  • I have already added NSLocationAlwaysUsageDescription in my plist, and I added the breakpoint, but I didn't notice a change, so I don't think the method is being called. – Kevin Nov 30 '16 at 18:46
  • Make sure u have not changed anything in viewDidLoad it must be same as you posted in your question for locationManager because it's working for me also try to simulate location on your simulator – Rajat Nov 30 '16 at 18:50
  • No, I have not changed the viewDidLoad. How do I simulate the location on the simulator? – Kevin Nov 30 '16 at 18:51
  • Check this - http://stackoverflow.com/questions/19624719/didupdatelocations-not-called and this - http://stackoverflow.com/questions/214416/set-the-location-in-iphone-simulator – Rajat Nov 30 '16 at 18:55
  • I've figured out how to simulate the location. Now when I select a location and run the code, I get the "Thread 1: breakpoint 3.1" error on map.removeAnnotation(newPin). – Kevin Nov 30 '16 at 19:01
  • Nevermind, I was foolish and didn't remove the breakpoint I previously put. Thanks for your help!! – Kevin Nov 30 '16 at 19:06
3

First you need to add annotation in didUpdateLocations method and then whenever any annotation is added then viewForAnnotation is called so here is the code and corresponding method to add pin in user current location :

//Adding Annotation on Current Location

 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        //Get Current Location
        let location = locations.last! as CLLocation
        let userLocation:CLLocation = locations[0] as CLLocation
        let myAnnotation: MKPointAnnotation = MKPointAnnotation()
        myAnnotation.coordinate = CLLocationCoordinate2DMake(userLocation.coordinate.latitude, userLocation.coordinate.longitude)
        myAnnotation.title = "Current location"
        map.addAnnotation(myAnnotation)
}

//Adding image to user current location pin

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

   guard !(annotation is MKUserLocation) else {
            let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "userLocation")
            annotationView.image = UIImage(named:"anyimage.png")
            return annotationView
        }
return nil
}

Feel free to ask if any further issue.

Shobhakar Tiwari
  • 7,862
  • 4
  • 36
  • 71