import UIKit import AVFAudio import AMapNaviKit class AmapViewController: UIViewController { // MARK: - 必须声明为强引用 private var driveManager: AMapNaviDriveManager! private var driveView: AMapNaviDriveView! private let speechSynthesizer = AVSpeechSynthesizer() private var startPoint: AMapNaviPoint! private var endPoint: AMapNaviPoint! // 自定义初始化方法 init(startpos: String, endpos: String) { super.init(nibName: nil, bundle: nil) self.startPoint = AmapViewController.parseCoord(from: startpos) self.endPoint = AmapViewController.parseCoord(from: endpos) print("导航---------------------: \(startPoint) \(endPoint)") } // 解析 "lat,lng" -> AMapNaviPoint private static func parseCoord(from string: String) -> AMapNaviPoint? { let components = string.split(separator: ",") guard components.count == 2, let lng = Double(components[0]), let lat = Double(components[1]) else { print("❌ 无效坐标格式: \(string)") return nil } return AMapNaviPoint.location(withLatitude: lat, longitude: lng) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() setupAMapComponents() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // 页面即将消失时停止导航 if driveManager != nil { driveManager.stopNavi() driveManager.allowsBackgroundLocationUpdates = false } } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) // 页面完全消失后清理资源 cleanupResources() } private func cleanupResources() { print("开始清理导航资源") // 停止语音合成 speechSynthesizer.stopSpeaking(at: .immediate) // 如果导航管理器存在,进行清理 if let manager = driveManager { // 停止导航 manager.stopNavi() // 禁用后台定位 manager.allowsBackgroundLocationUpdates = false // 清理代理 manager.delegate = nil // 如果视图存在,移除数据代表 if let view = driveView { manager.removeDataRepresentative(view) view.delegate = nil view.removeFromSuperview() } } // 销毁单例实例(关键步骤) AMapNaviDriveManager.destroyInstance() // 清空引用 driveManager = nil driveView = nil print("导航资源清理完成") } private func setupAMapComponents() { self.addNSNotification(); // 1. 初始化 DriveView(必须在主线程) // print("导航------------------ setupAMapComponents_1") DispatchQueue.main.async { // print("导航------------------ setupAMapComponents_2") self.driveView = AMapNaviDriveView(frame: self.view.bounds) // print("导航------------------ setupAMapComponents_3") self.driveView.autoresizingMask = [.flexibleWidth, .flexibleHeight] // print("导航------------------ setupAMapComponents_4") self.driveView.delegate = self // print("导航------------------ setupAMapComponents_5") self.view.addSubview(self.driveView) // print("导航------------------ setupAMapComponents_6") // 2. 初始化 DriveManager self.driveManager = AMapNaviDriveManager.sharedInstance() // print("导航------------------ setupAMapComponents_7") self.driveManager.delegate = self // print("导航------------------ setupAMapComponents_8") self.driveManager.allowsBackgroundLocationUpdates = true // print("导航------------------ setupAMapComponents_9") // 3. 确保对象非空再关联 if let manager = self.driveManager, let view = self.driveView { // print("导航------------------ setupAMapComponents_10") manager.addDataRepresentative(view) // print("导航------------------ setupAMapComponents_11") self.startNavigation() // print("导航------------------ setupAMapComponents_12") } else { print("Error: driveManager or driveView is nil") } // print("导航------------------ setupAMapComponents_13") } } private func startNavigation() { // print("导航------------------ startNavigation_1") // let startPoint = AMapNaviPoint.location(withLatitude: 39.989614, longitude: 116.481763)! // print("导航------------------ startNavigation_2") // let endPoint = AMapNaviPoint.location(withLatitude: 39.983456, longitude: 116.315495)! // print("导航------------------ startNavigation_3") driveManager.calculateDriveRoute( withStart: [startPoint], end: [endPoint], wayPoints: nil, drivingStrategy: .drivingStrategySingleDefault ) print("导航------------------ startNavigation_4") } @objc private func exitNavigation() { print("导航------------------ 退出导航,清理资源") // 停止导航 driveManager.stopNavi() driveManager.removeDataRepresentative(driveView) driveManager.delegate = nil // 移除导航视图 driveView.delegate = nil driveView.removeFromSuperview() driveView = nil // 销毁导航管理器 driveManager = nil // 关闭当前页面 - 修复:使用正确的退出方式 if let navigationController = navigationController { // 如果是在导航控制器中,使用 pop navigationController.popViewController(animated: true) } else { // 如果是 present 出来的,使用 dismiss dismiss(animated: true, completion: nil) } } private func addNSNotification(){ NotificationCenter.default.addObserver( forName: NSNotification.Name("ExitNavigation"), object: nil, queue: .main ) { _ in self.exitNavigation() } } } // MARK: - 代理方法 extension AmapViewController: AMapNaviDriveViewDelegate, AMapNaviDriveManagerDelegate { //View回调 func driveViewCloseButtonClicked(_ driveView: AMapNaviDriveView) { print("导航界面关闭按钮被点击") // 1. 立即停止所有导航相关服务 driveManager?.stopNavi() driveManager?.allowsBackgroundLocationUpdates = false // 2. 清理视图和代理关系 driveManager?.removeDataRepresentative(driveView) driveManager?.delegate = nil driveView.delegate = nil // 3. 从视图层次结构中移除 driveView.removeFromSuperview() // 4. 停止语音合成 speechSynthesizer.stopSpeaking(at: .immediate) // 5. 销毁导航管理器实例 AMapNaviDriveManager.destroyInstance() // 6. 清空引用 driveManager = nil // 7. 立即退出,不使用延迟 if let navigationController = navigationController { navigationController.popViewController(animated: true) } else { dismiss(animated: true, completion: nil) } } func driveView(_ driveView: AMapNaviDriveView, didChange showMode: AMapNaviDriveViewShowMode) { print("导航界面显示模式改变:\(showMode.rawValue)") } func driveView(_ driveView: AMapNaviDriveView, didChange trackMode: AMapNaviViewTrackingMode) { print("导航界面跟随模式改变:\(trackMode.rawValue)") } func driveView(_ driveView: AMapNaviDriveView, didChangeOrientation isLandscape: Bool) { print("导航界面横竖屏切换:isLandscape = \(isLandscape)") } func driveView(_ driveView: AMapNaviDriveView, didChangeDayNightType showStandardNightType: Bool) { print("导航界面白天/黑夜模式切换:isNight = \(showStandardNightType)") } func driveViewEdgePadding(_ driveView: AMapNaviDriveView) -> UIEdgeInsets { // 你可以根据自己 UI 布局返回合适的内边距,防止遮挡 let padding = UIEdgeInsets(top: 100, left: 50, bottom: 80, right: 60) print("请求导航界面可视区域边距:\(padding)") return padding } //导航回调 func driveManager(_ driveManager: AMapNaviDriveManager, error: Error) { print("导航------------------ ❌ 发生错误: \(error.localizedDescription)") } func driveManager(onCalculateRouteSuccess driveManager: AMapNaviDriveManager){ print("导航------------------ ✅ 路线规划成功(旧方法)") driveManager.startGPSNavi() } func driveManager(_ driveManager: AMapNaviDriveManager, onCalculateRouteSuccessWith type: AMapNaviRoutePlanType) { print("导航------------------ 路径规划成功,类型: \(type.rawValue)") driveManager.startGPSNavi() } func driveManager(_ driveManager: AMapNaviDriveManager, onCalculateRouteFailure error: Error) { print("导航------------------ ❌ 路线规划失败: \(error.localizedDescription)") } func driveManager(_ driveManager: AMapNaviDriveManager, onCalculateRouteFailure error: Error, routePlanType type: AMapNaviRoutePlanType) { print("导航------------------ ❌ 路线规划失败(新方法): \(error.localizedDescription),类型: \(type.rawValue)") } func driveManager(_ driveManager: AMapNaviDriveManager, didStartNavi naviMode: AMapNaviMode) { print("导航------------------ 🚗 已开始导航,模式: \(naviMode.rawValue)") } func driveManagerNeedRecalculateRoute(forYaw driveManager: AMapNaviDriveManager) { print("导航------------------ 出现偏航,需要重新计算路径") } func driveManagerNeedRecalculateRoute(forTrafficJam driveManager: AMapNaviDriveManager) { print("导航------------------ 遇到拥堵,重新规划路线") } func driveManager(_ driveManager: AMapNaviDriveManager, onArrivedWayPoint wayPointIndex: Int) { print("导航------------------ 到达途经点索引:\(wayPointIndex)") } func driveManagerIsNaviSoundPlaying(_ driveManager: AMapNaviDriveManager) -> Bool { print("导航------------------ 🔊 正在判断是否在播报语音") return false // 如果你有 TTS 系统播报时需返回 true } func driveManager(_ driveManager: AMapNaviDriveManager, playNaviSound soundString: String, soundStringType: AMapNaviSoundType) { print("导航------------------ 📢 导航播报: \(soundString),类型: \(soundStringType.rawValue)") // 示例:使用 AVSpeechSynthesizer 播放语音 let utterance = AVSpeechUtterance(string: soundString) utterance.voice = AVSpeechSynthesisVoice(language: "zh-CN") speechSynthesizer.speak(utterance) } func driveManagerDidEndEmulatorNavi(_ driveManager: AMapNaviDriveManager) { print("导航------------------ 🛑 模拟导航结束") } func driveManager(onArrivedDestination driveManager: AMapNaviDriveManager) { print("导航------------------ 🎯 到达目的地") } func driveManager(_ driveManager: AMapNaviDriveManager, onNaviPlay ringType: AMapNaviRingType) { print("导航------------------ 🔔 播放提示音,类型: \(ringType.rawValue)") } func driveManager(_ driveManager: AMapNaviDriveManager, update gpsSignalStrength: AMapNaviGPSSignalStrength) { print("导航------------------ 📡 GPS信号强度: \(gpsSignalStrength.rawValue)") } func driveManager(_ driveManager: AMapNaviDriveManager, postRouteNotification notifyData: AMapNaviRouteNotifyData) { print("导航------------------ 📌 路线通知信息: \(notifyData)") } func driveManager(_ driveManager: AMapNaviDriveManager, onSuggestChangeMainNaviRoute suggestChangeMainNaviRouteInfo: AMapNaviSuggestChangeMainNaviRouteInfo) { print("导航------------------ 🔄 建议切换主导航路线: \(suggestChangeMainNaviRouteInfo)") } }