How to get user location?

梦想的初衷 提交于 2019-12-02 07:11:55

问题


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


回答1:


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:




回答2:


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.



回答3:


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.



来源:https://stackoverflow.com/questions/45554220/how-to-get-user-location

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!