Mapbox iOS中NavigationMapViewDelegate代理方法未触发问题求助
问题排查与修复方案
核心问题
- 代理方法归属错误:你实现的
navigationViewController(_:didUpdate:with:rawLocation:)是NavigationViewControllerDelegate的方法,而非NavigationMapViewDelegate的方法,设置mapView.delegate = self不会触发该方法。 - 未启动导航流程:仅初始化了
NavigationMapView和NavigationViewController变量,但未实际创建路线、启动导航,也未给NavigationViewController设置代理。 - 空值强制解包风险:第一次触发时
previousLocation为nil,location.distance(from: previousLocation!)会直接崩溃。
修复步骤
1. 修正代理协议与方法
同时遵循NavigationViewControllerDelegate协议,确保代理设置正确:
class MapViewController: UIViewController, NavigationMapViewDelegate, NavigationViewControllerDelegate { // ... 原有代码 ... }
2. 完整启动导航流程
在viewDidLoad或合适时机创建路线并启动导航,同时设置NavigationViewController的代理:
override func viewDidLoad() { super.viewDidLoad() mapView = NavigationMapView(frame: view.bounds) mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight] view.addSubview(mapView) mapView.delegate = self mapView.userLocationStyle = .puck2D() // 示例:创建起点终点并启动导航 let origin = CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194) let destination = CLLocationCoordinate2D(latitude: 37.3352, longitude: -122.0322) let routeOptions = NavigationRouteOptions(coordinates: [origin, destination]) Directions.shared.calculate(routeOptions) { [weak self] result in guard let self = self else { return } switch result { case .success(let response): guard let route = response.routes.first else { return } let navigationOptions = NavigationOptions(styles: [DayStyle()]) self.navigationViewController = NavigationViewController(for: route, routeIndex: 0, options: navigationOptions) self.navigationViewController.delegate = self self.present(self.navigationViewController, animated: true) case .failure(let error): print("路线计算失败: \(error.localizedDescription)") } } }
3. 修复距离计算逻辑
处理previousLocation为空的情况,避免崩溃并正确累计行驶距离:
// 新增累计距离变量 private var accumulatedDistance: CLLocationDistance = 0 func navigationViewController(_ navigationViewController: NavigationViewController, didUpdate progress: RouteProgress, with location: CLLocation, rawLocation: CLLocation) { guard let previousLoc = previousLocation else { // 第一次记录当前位置 previousLocation = location return } let distance = location.distance(from: previousLoc) accumulatedDistance += distance if accumulatedDistance >= 1609.34 { print("用户已行驶至少1英里") // 调用你的指定函数 // yourTargetFunction() // 重置累计距离 accumulatedDistance = 0 } // 更新上一次位置 previousLocation = location }
4. 配置定位权限
在Info.plist中添加必要的定位权限描述:
NSLocationWhenInUseUsageDescriptionNSLocationAlwaysAndWhenInUseUsageDescription(如需后台定位)
额外说明
如果不需要完整导航UI,仅需监听位置计算距离,直接使用CLLocationManager会更轻量;测试时可使用模拟器的「模拟位置」功能选择路线,快速验证逻辑。
内容的提问来源于stack exchange,提问作者cyo
相关产品推荐
相关产品推荐

