How to get user location?

2020-04-11 10:35发布

I am trying to get the user's current location using the following code, but it doesn't work. I have added both NSLocationWhenInUseUsageDescription key and NSLocationAlwaysUsageDescription key to my Info.plist file. Below is the code

var locationManager = CLLocationManager();

override func viewDidLoad() {
        super.viewDidLoad()
        startReceivingLocationChanges();

    }
func startReceivingLocationChanges() {
     let authorizationStatus = CLLocationManager.authorizationStatus()
            if authorizationStatus != .authorizedAlways {
                // User has not authorized access to location information.
                print("not authorized");
                return
            }

        if !CLLocationManager.locationServicesEnabled() {
            print("not enabled");
            return
        }

        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
        locationManager.distanceFilter = 100.0  // In meters.

        locationManager.startUpdatingLocation()
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let lastLocation = locations.last!
        print(lastLocation)
    }

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print(error);
    }

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        print("inside didChangeAuthorization ");
    }

i have read through the apple documents and above is the code that apple suggests. What am i missing here ? Any kind of help is really appreciated. Thanks

EDIT for some reason requestAlwaysAuthorization() is not available. see the screenshot below enter image description here

3条回答
▲ chillily
2楼-- · 2020-04-11 11:17

for some reason requestAlwaysAuthorization() is not available.

requestAlwaysAuthorization() isn't available because you're working in macOS, and the documentation shows that that method is only available in iOS and watchOS. See the list of SDK's on the right side of the page, near the top:

list of SDKs

查看更多
够拽才男人
3楼-- · 2020-04-11 11:20

Just make sure the location manager is authorized to find user's location. You should call locationManager.requestAlwaysAuthorization() before calling for location updates.

Also check that your simulator debugging simulates the user location.

查看更多
小情绪 Triste *
4楼-- · 2020-04-11 11:34

The issue here is that on macOS prior to 10.15 one does not explicitly call to request location access like one does on iOS. The user permission prompt is automatically presented when you call startUpdatingLocation().

In your code above execution never gets to that call because your function startReceivingLocationChanges always returns in the first statement where it checks current status (which will be "status not yet determined" most likely). So it never gets to the startUpdatingLocation() call further down in that function and thus never prompts the user to allow location reporting.

In macOS 10.15 requestAlwaysAuthorization() is available, but doesn't seem to be required if you just need to use location when your app is in use.

Also, on macOS .authorized seems to be preferred over .authorizedAlways (documented to be synonyms), though with the addition of the requestAlwaysAuthorization() function in 10.15 they may change this (though the documentation has not been updated to indicate this having happened at the time of this answer).

If you are not calling requestAlwayAuthorization() then it seems that only the NSLocationWhenInUseUsageDescription info.plist key is needed.

Additionally, it is necessary to set the "Location" checkbox in "Hardened Runtime" under "Signing & Capabilities" for the macOS application project. This is required on Xcode 11.2.1 on macOS 10.14.6 where I'm testing this. Older setups, or ones not adopting the hardened runtime (now the default), may have to set this in a different location in the project build settings.

Here's the source for a NSViewController subclass that checks for location manager and the current location successfully in Xcode 11.2.1 on macOS 10.14.6:

import Cocoa
import CoreLocation

class ViewController: NSViewController, CLLocationManagerDelegate {

    let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()

        locationManager.delegate = self
        print("starting location update requests")
        locationManager.startUpdatingLocation()
    }


    func locationManager(_ manager: CLLocationManager,
                        didChangeAuthorization status: CLAuthorizationStatus) {
        print("location manager auth status changed to:" )
        switch status {
            case .restricted:
                print("status restricted")
            case .denied:
                print("status denied")

            case .authorized:
                print("status authorized")
                let location = locationManager.location
                print("location: \(String(describing: location))")

            case .notDetermined:
                print("status not yet determined")

            default:
                print("unknown state: \(status)")
        }
    }

    func locationManager(_ manager: CLLocationManager,
                            didFailWithError error: Error) {
        print( "location manager failed with error \(error)" )
    }
}

This works for me on macOS if I say yes to the "enable location services" prompt when I launch the app the first time.

Console output is (slightly obfuscated):

location manager auth status changed to: status not yet determined location manager auth status changed to: status authorized location: Optional(<+4X.48,-12X.62632228> +/- 65.00m (speed -1.00 mps / course -1.00) @ 11/15/19, 10:24:30 AM Pacific Standard Time)

Steps to make this sample:

  1. open Xcode and create a new macOS project
  2. Edit the ViewController supplied by the project template to match the above code
  3. Add the NSLocationWhenInUseUsageDescription key to the info.plist
  4. Check the "Location" checkbox under "Hardened Runtime" in the "Signing & Capabilities" section of the app target in the project settings.
查看更多
登录 后发表回答