You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mapbox iOS中NavigationMapViewDelegate代理方法未触发问题求助

问题排查与修复方案

核心问题

  1. 代理方法归属错误:你实现的navigationViewController(_:didUpdate:with:rawLocation:)是NavigationViewControllerDelegate的方法,而非NavigationMapViewDelegate的方法,设置mapView.delegate = self不会触发该方法。
  2. 未启动导航流程:仅初始化了NavigationMapView和NavigationViewController变量,但未实际创建路线、启动导航,也未给NavigationViewController设置代理。
  3. 空值强制解包风险:第一次触发时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中添加必要的定位权限描述:

  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysAndWhenInUseUsageDescription(如需后台定位)

额外说明

如果不需要完整导航UI,仅需监听位置计算距离,直接使用CLLocationManager会更轻量;测试时可使用模拟器的「模拟位置」功能选择路线,快速验证逻辑。

内容的提问来源于stack exchange,提问作者cyo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 18:50:16