最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

swiftui - CoreLocation not working in Swift, but only on MacOS - Stack Overflow

programmeradmin1浏览0评论

This location manager in swift is not receiving location updates for MacOS. For your information:

  • This same file is shared with the iOS instance of the app and works fine there.
  • This is not my device only, as the app was rejected by App Review because of the location not being updated.
  • I do have the necessary privacy tags in Info.plist
  • I tested the same code in AppDelegate with the same result
  • I am getting 0 for the location status, which means `.notDetermined'
  • This has been tested on a fresh install and I gave the app the necessary permissions in settings.
import SwiftUI
import CoreLocation
import Combine
import MapKit
import BackgroundTasks

/// Manages location-related services and permissions for the app.
class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
    
    /// Instance of `CLLocationManager` to handle location updates.
    private let locationManager = CLLocationManager()
    
    /// Published property to monitor the current authorization status.
    @Published var locationStatus: CLAuthorizationStatus?
    
    /// Published property to store the user's current location.
    @Published var location: CLLocation?
    
    /// Initializes the location manager, sets up permissions, and starts updating location.
    override init() {
        super.init()
        
        guard CLLocationManager.locationServicesEnabled() else {
            print("Location services are not enabled.")
            return
        }
        
        self.locationStatus = locationManager.authorizationStatus
        
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        
        if self.locationStatus == .notDetermined {
            locationManager.requestWhenInUseAuthorization()
            locationManager.requestAlwaysAuthorization()
        }
        
        locationManager.startUpdatingLocation()
    }
    
    /// Provides a string representation of the current authorization status.
    var statusString: String {
        guard let status = locationStatus else {
            return "unknown"
        }
        
        switch status {
            case .notDetermined: return "notDetermined"
            case .authorizedWhenInUse: return "authorizedWhenInUse"
            case .authorizedAlways: return "authorizedAlways"
            case .restricted: return "restricted"
            case .denied: return "denied"
            default: return "unknown"
        }
    }
    
    /// Handles changes in the location authorization status.
    /// - Parameters:
    ///   - manager: The `CLLocationManager` instance reporting the status change.
    ///   - status: The updated authorization status.
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        self.locationStatus = status
        
        print("Authorization status changed: \(status.rawValue)")
        
        #if os(tvOS)
        if status == .authorizedWhenInUse {
            locationManager.requestLocation()
        }
        #endif
    }
    
    func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
        let status = manager.authorizationStatus
        self.locationStatus = status
        
        print("Authorization status changed: \(status.rawValue)")
        
        if status == .authorized || status == .authorizedAlways || status == .authorized {
            locationManager.startUpdatingLocation()
        }
    }
    
    /// Updates the user's current location.
    /// - Parameters:
    ///   - manager: The `CLLocationManager` instance providing the location update.
    ///   - locations: An array of updated location objects.
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let location = locations.last else { return }
        if self.location == nil {
            self.location = location
        }
    }
    
    /// Handles errors encountered by the location manager.
    /// - Parameters:
    ///   - manager: The `CLLocationManager` instance reporting the error.
    ///   - error: The error encountered by the location manager.
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("Location manager failed with error: \(error.localizedDescription)")
    }
}

This location manager in swift is not receiving location updates for MacOS. For your information:

  • This same file is shared with the iOS instance of the app and works fine there.
  • This is not my device only, as the app was rejected by App Review because of the location not being updated.
  • I do have the necessary privacy tags in Info.plist
  • I tested the same code in AppDelegate with the same result
  • I am getting 0 for the location status, which means `.notDetermined'
  • This has been tested on a fresh install and I gave the app the necessary permissions in settings.
import SwiftUI
import CoreLocation
import Combine
import MapKit
import BackgroundTasks

/// Manages location-related services and permissions for the app.
class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
    
    /// Instance of `CLLocationManager` to handle location updates.
    private let locationManager = CLLocationManager()
    
    /// Published property to monitor the current authorization status.
    @Published var locationStatus: CLAuthorizationStatus?
    
    /// Published property to store the user's current location.
    @Published var location: CLLocation?
    
    /// Initializes the location manager, sets up permissions, and starts updating location.
    override init() {
        super.init()
        
        guard CLLocationManager.locationServicesEnabled() else {
            print("Location services are not enabled.")
            return
        }
        
        self.locationStatus = locationManager.authorizationStatus
        
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        
        if self.locationStatus == .notDetermined {
            locationManager.requestWhenInUseAuthorization()
            locationManager.requestAlwaysAuthorization()
        }
        
        locationManager.startUpdatingLocation()
    }
    
    /// Provides a string representation of the current authorization status.
    var statusString: String {
        guard let status = locationStatus else {
            return "unknown"
        }
        
        switch status {
            case .notDetermined: return "notDetermined"
            case .authorizedWhenInUse: return "authorizedWhenInUse"
            case .authorizedAlways: return "authorizedAlways"
            case .restricted: return "restricted"
            case .denied: return "denied"
            default: return "unknown"
        }
    }
    
    /// Handles changes in the location authorization status.
    /// - Parameters:
    ///   - manager: The `CLLocationManager` instance reporting the status change.
    ///   - status: The updated authorization status.
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        self.locationStatus = status
        
        print("Authorization status changed: \(status.rawValue)")
        
        #if os(tvOS)
        if status == .authorizedWhenInUse {
            locationManager.requestLocation()
        }
        #endif
    }
    
    func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
        let status = manager.authorizationStatus
        self.locationStatus = status
        
        print("Authorization status changed: \(status.rawValue)")
        
        if status == .authorized || status == .authorizedAlways || status == .authorized {
            locationManager.startUpdatingLocation()
        }
    }
    
    /// Updates the user's current location.
    /// - Parameters:
    ///   - manager: The `CLLocationManager` instance providing the location update.
    ///   - locations: An array of updated location objects.
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let location = locations.last else { return }
        if self.location == nil {
            self.location = location
        }
    }
    
    /// Handles errors encountered by the location manager.
    /// - Parameters:
    ///   - manager: The `CLLocationManager` instance reporting the error.
    ///   - error: The error encountered by the location manager.
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("Location manager failed with error: \(error.localizedDescription)")
    }
}

Share Improve this question asked Jan 19 at 19:53 azekkaniazekkani 331 silver badge6 bronze badges 14
  • Please see stackoverflow/a/74915706/20287183 for details on how to properly setup and use CLLocationManager. – HangarRash Commented Jan 19 at 19:57
  • @HangarRash, I tried the code you linked and it still doesn't work. – azekkani Commented Jan 19 at 20:11
  • Many issues with your code. For starters: you should not be asking for requestWhenInUseAuthorization and requestAlwaysAuthorization at the same time (either one, or the other). You shouldn't call startUpdatingLocation immediately after that (authorization is async call). You are calling it from init, so you have to make sure this LocationManager is a singleton, and is only called when there's already some UI to display the authorization form over. Also @HangarRash provided a link to a good answer. What exactly didn't work for you when you "tried that code"? – timbre timbre Commented Jan 19 at 21:08
  • @timbretimbre. Perhaps I wasn't clear enough with my response. I implemented the changes in @HangarRash 's response and found the same results as detailed in the original post. No location is being returned and the status remains 0 or .notDetermined. – azekkani Commented Jan 19 at 21:47
  • 1 @azekkani Without seeing how you implemented the code I suggested, there's no way to know what you are doing wrong with that attemp. But the code you posted has many, many problems. It would help to show your attempt at the code I suggested so we can help you find the issue. – HangarRash Commented Jan 19 at 22:57
 |  Show 9 more comments

1 Answer 1

Reset to default -1

I was able to fix this problem by removing the Hardened Runtime Capability for MacOS. This oddly fixed the problem and allowed my app to get location updates again. Huge Thanks to @Paulw11

发布评论

评论列表(0)

  1. 暂无评论