0 Replies
      Latest reply on Feb 9, 2020 4:50 PM by tkerridge-gruntify
      tkerridge-gruntify Level 1 Level 1 (0 points)

        It seems that when using Core Location on Apple Watch, and requesting permission via CLLocationManager's requestWhenInUseAuthorization() on a watchOS app that requires an iOS app to be installed, and choosing "Allow Once", the authorizedWhenInUse status is not reflected on watchOS and is instead left on notDetermined. Attempting to request again does nothing. What's also odd is that the request prompt doesn't seem to come up on the watch, and instead only ever shows up on the iOS app.

         

        If I choose to make the watchOS app support installation without iOS app, it seems to work, but I require the iOS in this case so that's not an option (note that in this case, I can't seem to change the permission status after choosing something?).

         

        I'm out of ideas of what I'm doing wrong, as other apps (system, eg. Weather, and third party, eg. Uber) appear to work in some capacity, and at least show the permission request popup on the Watch rather than only the iPhone.

         

        Included basic code and such below:

         

        WatchKit Extension Interface Controller (not working as expected):

        import WatchKit
        import CoreLocation
        
        class InterfaceController: WKInterfaceController, CLLocationManagerDelegate {
        
            let manager = CLLocationManager()
          
            /// Single button in center of the interface.
            @IBOutlet weak var button: WKInterfaceButton!
          
            override func awake(withContext context: Any?) {
                super.awake(withContext: context)
                manager.delegate = self
            }
          
            @IBAction func buttonTapped() {
                switch CLLocationManager.authorizationStatus() {
                case .notDetermined:
                    // Permission prompt only shows up on iPhone (if it's running).
                    // Sometimes it will prompt saying to approve or deny on iPhone.
                    // Does nothing if previously selected "Allow Once". Thinks it's still not determined.
                    manager.requestWhenInUseAuthorization()
                case .restricted:
                    break
                case .denied:
                    break
                case .authorizedAlways:
                    break
                case .authorizedWhenInUse:
                    break
                @unknown default:
                    break
                }
            }
          
            func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
                debugPrint(#function, status.rawValue)
                switch status {
                case .notDetermined:
                    button.setTitle("Allow Permission")
                case .restricted:
                    button.setTitle("Restricted")
                case .denied:
                    button.setTitle("Denied")
                case .authorizedAlways:
                    button.setTitle("Allowed Always")
                case .authorizedWhenInUse:
                    button.setTitle("Allowed When in Use")
                @unknown default:
                    button.setTitle("?")
                }
            }
          
            func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
                debugPrint(#function, error.localizedDescription)
            }
          
            func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
                debugPrint(#function, locations)
            }
          
            func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
                debugPrint(#function, newHeading)
            }
            func locationManagerShouldDisplayHeadingCalibration(_ manager: CLLocationManager) -> Bool {
                debugPrint(#function)
                return true
            }
          
        }

         

        iOS ViewController (works as expected):

        import UIKit
        import CoreLocation
        
        class ViewController: UIViewController, CLLocationManagerDelegate {
        
            let button = UIButton()
            let manager = CLLocationManager()
           
            override func viewDidLoad() {
                super.viewDidLoad()
               
                view.backgroundColor = .systemBackground
                view.addSubview(button)
               
                button.setTitleColor(.label, for: .normal)
                button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
               
                manager.delegate = self
            }
           
            override func viewDidLayoutSubviews() {
                super.viewDidLayoutSubviews()
               
                button.center = view.center
                button.bounds.size = CGSize(width: 300, height: 100)
            }
           
            @IBAction func buttonTapped() {
                switch CLLocationManager.authorizationStatus() {
                case .notDetermined:
                    manager.requestWhenInUseAuthorization()
                case .restricted:
                    break
                case .denied:
                    break
                case .authorizedAlways:
                    break
                case .authorizedWhenInUse:
                    break
                @unknown default:
                    break
                }
            }
           
            func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
                debugPrint(#function, status.rawValue)
                switch status {
                case .notDetermined:
                    button.setTitle("Allow Permission", for: .normal)
                case .restricted:
                    button.setTitle("Restricted", for: .normal)
                case .denied:
                    button.setTitle("Denied", for: .normal)
                case .authorizedAlways:
                    button.setTitle("Allowed Always", for: .normal)
                case .authorizedWhenInUse:
                    button.setTitle("Allowed When in Use", for: .normal)
                @unknown default:
                    button.setTitle("Unknown Permission Status", for: .normal)
                }
            }
           
            func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
                debugPrint(#function, error.localizedDescription)
            }
           
            func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
                debugPrint(#function, locations)
            }
           
            func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
                debugPrint(#function, newHeading)
            }
           
            func locationManagerShouldDisplayHeadingCalibration(_ manager: CLLocationManager) -> Bool {
                debugPrint(#function)
                return true
            }
           
        }

         

        Included in `Info.plist` (iOS, WatchKit, and WatchKit Extension):

        <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>

        <string>to show your location</string>

        <key>NSLocationAlwaysUsageDescription</key>

        <string>to show your location</string>

        <key>NSLocationUsageDescription</key>

        <string>to show your location</string>

        <key>NSLocationWhenInUseUsageDescription</key>

        <string>to show your location</string>

         

        Deployment Targets:

        iOS: 13.2
        watchOS: 6.1

         

        Xcode: 11.3.1 (11C504)

        macOS: 10.15.3 (19D76)

         

        Edit:

        Potentially similar issue from a while ago: https://forums.developer.apple.com/thread/99260