ios – Handling location updates in background for widget refresh


I’am developing an iOS widget for my weather app, where the user can set the widget to “My location”. This means the widget needs to be refreshed on location changes. Since a widget can’t run a location manager in the background, apple tech support wrote that you have to setup a location manager in the main app and share the updated location data over App groups to the widget. This part works fine. I also managed to setup a location manager running in the background, but it uses too much battery and shows always the location indicator on top (blue bar) if the app is running, but I don’t need this since its not a navigation app or something similar. How to configure a lightweight location manager running in the background?

class WidgetLocationManager: NSObject, CLLocationManagerDelegate {
    static let shared: WidgetLocationManager = WidgetLocationManager()
    
    let manager = CLLocationManager()
    
    override init() {
        super.init()
        
        manager.delegate = self
        manager.desiredAccuracy = kCLLocationAccuracyKilometer
        manager.distanceFilter = 1000
        manager.allowsBackgroundLocationUpdates = true
        manager.pausesLocationUpdatesAutomatically = false
        manager.activityType = .other
        manager.showsBackgroundLocationIndicator = false
    }
    
    func setupWidgetLocationManager() {
        manager.requestWhenInUseAuthorization()
        
        manager.startUpdatingLocation()
        manager.startMonitoringSignificantLocationChanges()
    }
    
    func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
        if manager.authorizationStatus == .notDetermined || manager.authorizationStatus == .denied || manager.authorizationStatus == .restricted {
            manager.stopUpdatingLocation()
            manager.stopMonitoringSignificantLocationChanges()
        }
        
        if manager.authorizationStatus == .authorizedAlways || manager.authorizationStatus == .authorizedWhenInUse {
            manager.startUpdatingLocation()
            manager.startMonitoringSignificantLocationChanges()
        }
    }
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        
        if let newestLocation = locations.last {
            UserDefaults(suiteName: "group.com.xxx")?.set(Double(newestLocation.coordinate.latitude), forKey: "newest_location_latitude")
            UserDefaults(suiteName: "group.com.xxx")?.set(Double(newestLocation.coordinate.longitude), forKey: "newest_location_longitude")
            UserDefaults(suiteName: "group.com.xxx")?.set(Double(newestLocation.altitude), forKey: "newest_location_altitude")
            
            WidgetCenter.shared.reloadAllTimelines()
        }
    }
    
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        
    }
}

Capability for background modes location is set, also mandatory strings in info.plist for location privacy info.

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img