Swift 100%
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// LocationManager.swift — position de l'utilisateur (demande « pendant3// l'utilisation », mises à jour continues pour le point bleu et l'origine4// des itinéraires).5import Foundation6import CoreLocation78@MainActor9final class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {10 @Published var location: CLLocationCoordinate2D?11 @Published var speedKmh: Double? // vitesse GPS en km/h (nil si inconnue)12 @Published var course: Double? // cap GPS en degrés vrais (nil si inconnu)13 @Published var authorized = false1415 private let manager = CLLocationManager()1617 override init() {18 super.init()19 manager.delegate = self20 manager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters21 }2223 func request() {24 switch manager.authorizationStatus {25 case .notDetermined: manager.requestWhenInUseAuthorization()26 case .authorizedWhenInUse, .authorizedAlways: manager.startUpdatingLocation()27 default: break28 }29 }3031 nonisolated func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {32 let status = manager.authorizationStatus33 Task { @MainActor in34 self.authorized = (status == .authorizedWhenInUse || status == .authorizedAlways)35 if self.authorized { self.manager.startUpdatingLocation() }36 }37 }3839 nonisolated func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {40 guard let loc = locations.last else { return }41 let c = loc.coordinate42 let kmh = loc.speed >= 0 ? loc.speed * 3.6 : nil43 let crs = loc.course >= 0 ? loc.course : nil44 Task { @MainActor in45 self.location = c46 self.speedKmh = kmh47 self.course = crs48 }49 }5051 nonisolated func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {}52}53