#if CARPLAY_DEMO import CoreLocation import Observation /// Sperrt die Libelle, sobald das Fahrzeug schneller als Schrittgeschwindigkeit /// fährt. /// /// Ausrichten passiert im Stand oder im Zentimeterbereich davor. Eine Anzeige, /// die während der Fahrt etwas zu lesen gäbe, wäre Ablenkung ohne Nutzen – also /// gibt es sie dort nicht. Die Grenze ist bewusst technisch erzwungen und nicht /// bloss eine Zusage im Text. @Observable final class CarPlaySpeedGate: NSObject, CLLocationManagerDelegate { static let shared = CarPlaySpeedGate() /// Fünf km/h: schneller als Rangieren, langsamer als jede Verkehrssituation, /// in der jemand aufs Display sehen dürfte. static let limit: CLLocationSpeed = 5.0 / 3.6 private(set) var isStationary = true private(set) var speed: CLLocationSpeed? @ObservationIgnored private let manager = CLLocationManager() private override init() { super.init() manager.delegate = self manager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters } func start() { // Fuer Screenshots laesst sich die Geschwindigkeit vorgeben (in km/h); // eine simulierte GPS-Fahrt nur fuer ein Standbild waere unverhaeltnis- // maessig. Ohne die Variable zaehlt ausschliesslich der echte Sensor. if let forced = ProcessInfo.processInfo.environment["CARPLAY_DEMO_SPEED"].flatMap(Double.init) { speed = forced / 3.6 isStationary = forced / 3.6 <= Self.limit return } manager.requestWhenInUseAuthorization() manager.startUpdatingLocation() } /// Nur für die Demo-Sequenz: erzwingt den Fahrzustand, damit sich die /// Sperre zeigen lässt, ohne eine GPS-Fahrt zu simulieren. func setDemoDriving(_ driving: Bool) { speed = driving ? 30 / 3.6 : 0 isStationary = !driving } func stop() { manager.stopUpdatingLocation() } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let location = locations.last else { return } // CoreLocation meldet im Stand eine negative Geschwindigkeit: der Wert // ist dann schlicht unbekannt. Das als "fährt" zu werten, würde die // Funktion genau dort abschalten, wo sie gebraucht wird – auf dem // Stellplatz, oft unter Bäumen mit schlechtem Empfang. guard location.speed >= 0 else { speed = nil isStationary = true return } speed = location.speed isStationary = location.speed <= Self.limit } func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { speed = nil isStationary = true } } #endif