Live location tracking: continuous foreground updates (250m filter) + significant-change background monitoring; list/widget refresh and geofences follow the user, re-fetch on every move

This commit is contained in:
FuelBoard Contributor
2026-08-11 16:16:46 +01:00
parent 75629b39b5
commit c5050df445
+41 -3
View File
@@ -96,7 +96,7 @@ struct ContentView: View {
.tabItem { Label("Alerts", systemImage: "bell.fill") }
}
.onAppear {
locationManager.requestUpdate()
locationManager.startForegroundTracking()
monitor.update(stations: stations, favourites: refreshedFavourites,
fuel: selectedFuel, radiusKM: alertsRadius)
monitor.setEnabled(alertsEnabled)
@@ -104,10 +104,12 @@ struct ContentView: View {
}
.onChange(of: scenePhase) { _, newPhase in
if newPhase == .active {
locationManager.requestUpdate()
locationManager.startForegroundTracking()
monitor.update(stations: stations, favourites: refreshedFavourites,
fuel: selectedFuel, radiusKM: alertsRadius)
Task { await refresh() }
} else {
locationManager.stopForegroundTracking()
}
}
.onChange(of: locationManager.current) { _, newLocation in
@@ -123,6 +125,9 @@ struct ContentView: View {
monitor.setEnabled(newValue)
monitor.update(stations: stations, favourites: refreshedFavourites,
fuel: selectedFuel, radiusKM: alertsRadius)
if newValue {
locationManager.startBackgroundTracking()
}
}
.onChange(of: alertsRadius) { _, newValue in
FuelStore.saveAlertsRadius(newValue)
@@ -284,15 +289,48 @@ final class LocationManager: NSObject, ObservableObject, @preconcurrency CLLocat
super.init()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyHundredMeters
manager.distanceFilter = 250 // metres re-fires while driving
manager.pausesLocationUpdatesAutomatically = true
}
func requestUpdate() {
/// Continuous tracking while the app is in the foreground, so the list
/// re-fetches around the user's new position as they drive.
func startForegroundTracking() {
switch manager.authorizationStatus {
case .notDetermined:
manager.requestWhenInUseAuthorization()
manager.requestLocation()
case .authorizedWhenInUse, .authorizedAlways:
manager.startUpdatingLocation()
default:
break
}
}
/// One-shot fix (first launch / after permission grant).
func requestUpdate() {
manager.requestLocation()
}
/// Background wake-ups on significant movement. Needs Always permission;
/// called once the user enables alerts so geofences + prices follow them.
func startBackgroundTracking() {
guard manager.authorizationStatus == .authorizedAlways else { return }
manager.startMonitoringSignificantLocationChanges()
}
func stopForegroundTracking() {
// Significant-change monitoring keeps running in the background.
manager.stopUpdatingLocation()
}
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
switch manager.authorizationStatus {
case .authorizedAlways:
manager.startMonitoringSignificantLocationChanges()
manager.startUpdatingLocation()
case .authorizedWhenInUse:
manager.startUpdatingLocation()
default:
break
}