How to get user location?

后端 未结 3 1186
忘了有多久
忘了有多久 2021-01-20 09:06

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

3条回答
  •  迷失自我
    2021-01-20 09:27

    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.

提交回复
热议问题