0
votes

I am using a collection view and collection view reusable header. In the header, i am trying to get the user's location. I keep getting this error:

   Trying to start MapKit location updates without prompting for    
   location authorization. Must call -[CLLocationManager    
   requestWhenInUseAuthorization] or -[CLLocationManager    
   requestAlwaysAuthorization] first.

I looked at this question: Location Services not working in iOS 8 and none of the proposed solutions worked for me. I have added the keys (both NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription) to my info.Plist and that did not help. The app never requests the user to get it's location. Here is my code:

EDIT: my code now:

   import UIKit
   import MapKit
   import Parse
   import ParseUI
   import CoreLocation

   class ReusableHeaderMap: UICollectionReusableView, CLLocationManagerDelegate {
let locationManager = CLLocationManager()

@IBOutlet weak var newMap: MKMapView!


override func awakeFromNib() {
    locationManager.delegate = self
    let status = CLLocationManager.authorizationStatus()
    if status == CLAuthorizationStatus.Denied {

    }
    else if status == CLAuthorizationStatus.NotDetermined {
        self.locationManager.requestAlwaysAuthorization()
    }
    else if status == CLAuthorizationStatus.AuthorizedAlways {
        self.locationManager.startUpdatingLocation()
    }
    else {
        print("it took the else route")

    }

    print("status is \(status)")
    self.newMap.layer.cornerRadius = 8
    self.newMap.clipsToBounds = true

}

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    if locations.count > 0 {
        locationManager.stopUpdatingLocation()
        let location1 = locations.first as CLLocation!
        let mapSpan = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
        let mapRegion = MKCoordinateRegion(center: location1.coordinate, span: mapSpan)
        self.newMap.setRegion(mapRegion, animated: true)
    }
}


func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {

    if status == CLAuthorizationStatus.Denied {
        print("there will be limited functionaliy")
    }
    else if status == CLAuthorizationStatus.AuthorizedAlways {
        self.locationManager.startUpdatingLocation()
    }
    else {
        print("it took the else route")
      }
   }


}

my info.plist has this key:

  <key>NSLocationAlwaysUsageDescription</key>
<string>Get User Location</string>
1
I assume that you are testing on the device. delete the app from the device and try it again.casillas
I tried this and it did not work, I still receive the same error message.jjjjjjjj
What value are you getting back from CLLocationManager.authorizationStatus()? And is your didChangeAuthorizationStatus() method being called?Duncan C
the status is NotDetermined. And yes, the didCHangeAuthorizationStatus() is being called. in there, I have "else if status == CLAuthorizationStatus.NotDetermined { self.locationManager.requestWhenInUseAuthorization() }", but it never gives a prompt to the user to ask for authorization.jjjjjjjj

1 Answers

1
votes

The error message is telling you what you have to do. You need to make a call to

self.locationManager.requestWhenInUseAuthorization() 

or

self.locationManager.requestAlwaysAuthorization()

In your code before you attempt to start up the location manager. That step is in addition to adding the NSLocationAlwaysUsageDescription and/or NSLocationWhenInUseUsageDescription keys to info.plist.

See the docs on those methods for more information.

(Looking at the code you posted, you aren't setting things up correctly. You can't just call requestWhenInUseAuthorization and then startUpdatingLocation immediately after.)

As the docs say:

When the current authorization status is kCLAuthorizationStatusNotDetermined, this method runs asynchronously and prompts the user to grant permission to the app to use location services.

The key word there is asynchronously.

You need to make that call, then implement the locationManager:didChangeAuthorizationStatus: method. That method (didChangeAuthorizationStatus) will be called if the user grants your app permission to use location services.

Your code should look more like this:

override func awakeFromNib() 
{
  locationManager.delegate = self
  let status = locationManager.status
  if (status == kCLAuthorizationStatusNotDetermined)
  {
    locationManager.requestWhenInUseAuthorization()
  }
  else if (status == kCLAuthorizationStatusAuthorized)
  {
    locationManager.startUpdatingLocation()
  }
  else
  {
    //Handle other error cases here.
  }
  newMap.layer.cornerRadius = 8
  newMap.clipsToBounds = true
}

optional func locationManager(_ manager: CLLocationManager,
  didChangeAuthorizationStatus status: CLAuthorizationStatus)
{
  locationManager.startUpdatingLocation()
}