import CarPlay import MapKit class CarPlaySceneDelegate: NSObject { var interfaceController: CPInterfaceController? var mapTemplate: CPMapTemplate? var navigationSession: CPNavigationSession? // MARK: - Navigation Actions func startNavigation( instruction: String, distance: Double, eta: Double, maneuverType: Int ) { guard let mapTemplate = mapTemplate else { return } let origin = MKMapItem( placemark: MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: 0, longitude: 0)) ) let destination = MKMapItem( placemark: MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: 0, longitude: 0)) ) let trip = CPTrip(origin: origin, destination: destination) let session = mapTemplate.startNavigationSession(for: trip) self.navigationSession = session updateManeuver(instruction: instruction, distance: distance, maneuverType: maneuverType) updateArrivalEstimates(eta: eta) } func updateManeuver(instruction: String, distance: Double, maneuverType: Int) { guard let session = navigationSession else { return } let maneuver = CPManeuver() maneuver.instructionVariants = [instruction] if let color = maneuverColor(for: maneuverType) { maneuver.symbolColor = color } let distanceEstimate = CPTravelEstimates( distance: Measurement(value: distance, unit: UnitLength.meters), timeRemaining: 0 ) session.updateManeuvers([maneuver], travelEstimates: distanceEstimate) } func updateArrivalEstimates(eta: Double) { guard let session = navigationSession else { return } let arrivalEstimate = CPTravelEstimates( distance: Measurement(value: 0, unit: UnitLength.meters), timeRemaining: eta ) // `updatingArrival` is deprecated; for iOS 15+ use `updating(_:)` on the maneuver's arrivalEstimates. // We keep this for broad compatibility. session.updatingArrival(to: arrivalEstimate) } func updateLocation(lat: Double, lng: Double, bearing: Double) { let center = CLLocationCoordinate2D(latitude: lat, longitude: lng) let region = MKCoordinateRegion( center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01) ) mapTemplate?.showPanningInterface(animated: true) } func stopNavigation() { guard let session = navigationSession else { return } session.cancel() self.navigationSession = nil mapTemplate?.hideTripPreviews() } // MARK: - Helpers private func maneuverColor(for type: Int) -> UIColor? { switch type { case 4: return .systemGreen case 2, -2: return .systemBlue default: return nil } } } // MARK: - Shared State class CarPlayState { static let shared = CarPlayState() weak var sceneDelegate: CarPlaySceneDelegate? private init() {} }