17

I am trying to implement a basic map view and add a user's current location to the map as an annotation. I have added the requestwheninuse key to my info.plist and imported coreLocation.

In my view controller's did load method, I have the following:

locManager.requestWhenInUseAuthorization()
var currentLocation : CLLocation

if(CLLocationManager.authorizationStatus() == CLAuthorizationStatus.AuthorizedWhenInUse){

    currentLocation = locManager.location
    println("currentLocation is \(currentLocation)")      
}
else{
    println("not getting location")
    // a default pin
}

I am getting the prompt re. permission to retrieve location. As this is happening I am getting my print saying not getting location, obviously because this runs before the user gets a chance to tap OK. If I elave the app and come back in I can retrieve the location and add it to the map. However, I want when the user taps OK the first time to be able to then grab the current location and add it to the map there and then. How can I achieve this? I have the following method for adding a pin:

func addPin(location2D: CLLocationCoordinate2D){
    self.mapView.delegate = self
    var newPoint = MKPointAnnotation()
    newPoint.coordinate = location2D
    self.mapView.addAnnotation(newPoint)
}
user2363025
  • 6,365
  • 19
  • 48
  • 89

1 Answers1

41

In order to do that, you need to implement the methoddidChangeAuthorizationStatus for your location manager delegate which is called shortly after CLLocationManager is initialized.

First, at the top of the file don't forget to add : import CoreLocation

To do that, in your class where you are using the location, add the delegate protocol. Then in the viewDidLoad method (or applicationDidFinishLaunching if you are in the AppDelegate) initialize your location manager and set its delegate property to self:

class myCoolClass: CLLocationManagerDelegate {
    var locManager: CLLocationManager!

    override func viewDidLoad() {
        locManager = CLLocationManager()
        locManager.delegate = self
    }
 }

Finally, implement the locationManager(_ didChangeAuthorizationStatus _) method in the body of your class that you declared previously, this method will be called when the status of the authorization is changed, so as soon as your user clicked the button. You can implement it like this:

private func locationManager(manager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
    switch status {
    case .notDetermined:
        // If status has not yet been determied, ask for authorization
        manager.requestWhenInUseAuthorization()
        break
    case .authorizedWhenInUse:
        // If authorized when in use
        manager.startUpdatingLocation()
        break
    case .authorizedAlways:
        // If always authorized
        manager.startUpdatingLocation()
        break
    case .restricted:
        // If restricted by e.g. parental controls. User can't enable Location Services
        break
    case .denied:
        // If user denied your app access to Location Services, but can grant access from Settings.app
        break
    default:
        break
    }
}

Swift 4 - New enum syntax

For Swift 4, just switch the first letter of each enum case to lowercase (.notDetermined, .authorizedWhenInUse, .authorizedAlways, .restricted and .denied)

That way you can handle each and every case, wether the user just gave its permission or revoked it.

Krunal Nagvadia
  • 1,083
  • 2
  • 12
  • 33
The Tom
  • 2,790
  • 6
  • 29
  • 33
  • Thanks for the response. The line locManger.delegate = self is giving me an error 'expected declaration' – user2363025 Jun 19 '15 at 11:26
  • @user2363025 can you elaborate ? Click on the error and it should tell you more – The Tom Jun 19 '15 at 11:28
  • That is all the error says. No additional info is popping up on hover. I saw here http://stackoverflow.com/questions/24121761/how-to-use-corelocation-with-swift that maybe I'm supposed to define locManager in the appdelegate? I am also getting errors in every case of the switch statement saying that each of the methods cannot be called with no arguments whether I have defined the locManager in appdelegate or my view controller – user2363025 Jun 19 '15 at 11:34
  • Where did you call locManager.delegate = self and where did you place your function ? – The Tom Jun 19 '15 at 11:38
  • Initially.. I put locManager.delegate = self right after var locManager = CLLocationManager() within my view controller which has the map view and called func locationManager right underneath. Then I tried moving the func locationManager into the view did load of my view controller with the map. Then I saw the link posted above and moved the var locationManager: CLLocationManager = CLLocationManager() locationManager.delegate = self into the app delegate and left the func locationManager into the didFinishLaunchingWithOptions in appdelegate – user2363025 Jun 19 '15 at 11:45
  • See edit for changes. Delegate need to be set inside viewDidLoad. – The Tom Jun 19 '15 at 11:58
  • Sorry had a typo. I am now just getting the error for each method in every case of the switch saying that cannot invoke said method with no arguments – user2363025 Jun 19 '15 at 12:57
  • The errors updated after a clean to : (CLLocationManager! didChangeAuthorizationStatus: CLAuthorizationStatus) -> () does not have a member names requestWhenInUseAuthorization and so on for each case in the switch – user2363025 Jun 19 '15 at 13:29
  • Did you import CoreLocation at the beginning of your file ? – The Tom Jun 19 '15 at 13:44
  • Yes I've included that. Originally, as in the question above I was getting the prompt and retrieving location..so I'm not sure what the issue is here? – user2363025 Jun 19 '15 at 13:48
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/81009/discussion-between-the-tom-and-user2363025). – The Tom Jun 19 '15 at 14:00
  • I initialized `CLLocationManager` in `viewDidLoad()` but the function `locationManager:didChangeAuthorizationStatus:` is never called. I also put a breakpoint inside the function but nothing happens. What should I do? – Emm Dec 17 '19 at 12:31