越南地图导航 3.0.1

越南地图导航 3.0.1

nhatpvThanhdt 维护。



 
依赖
VietMapCoreNavigation= 3.0.0
VietMap~> 2.0.0
VietMapSolar~> 1.0.3
VietMapSpeech~> 2.0.1
 

  • NhatPV
Flitsmeister Navigation iOS Splash

Flitsmeister Navigation SDK for iOS 是基于 Mapbox Navigation SDK v0.21 的分支构建的,该版本构建在 Mapbox Directions API (v0.23.0) 之上,并包含获取计时导航说明所需的所有逻辑。

使用此SDK,您可以在自己的iOS应用中实现逐段导航,同时托管自己的地图瓦片和方向API。

为什么要分叉

  1. Mapbox 决定在其导航SDK中添加一个闭源组件,并引入了一个非开源许可证。Flitsmeister 希望得到一个开源解决方案。
  2. Mapbox 决定在其SDK中添加遥测。我们无法在不调整源代码的情况下将其关闭。
  3. 我们希望在不需要向Mapbox支付每MAU费用且不使用Mapbox API密钥的情况下使用SDK。

所有问题均通过此SDK解决。

我们做了哪些更改

  • 删除了EventManager及其所有引用,该管理器收集了我们不希望发送的遥测数据
  • Mapbox SDK(版本4.3)切换到Maplibre Maps SDK(版本5.12.2)
  • 在NavigationMapView构造函数中添加了可选的配置参数,用于自定义某些属性,例如路线颜色

入门指南

如果您希望在自己的项目中使用此库,必须遵循以下步骤

  1. 安装Carthage
    • 打开终端
    • [可选] 在M1 Mac上更改终端到bash: chsh -s /bin/bash
    • 安装Homebrew: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
    • 安装Carthage: brew install carthage
  2. 创建一个新的XCode项目
  3. 创建Cartfile
    • 打开终端
    • 更改位置到XCode项目的根目录: cd path/to/Project
    • 创建Cartfile: touch Cartfile
    • 新文件将被添加: Cartfile
  4. 通过前往您的应用程序项目文件 -> 包依赖项 -> 点击 '+' -> https://github.com/maplibre/maplibre-gl-native-distribution -> 'Exact' 5.12.2 添加Maplibre Maps SPM(Swift Package Manager)依赖项
  5. 向Cartfile添加依赖
    github "flitsmeister/flitsmeister-navigation-ios" ~> 1.0.6
    
  6. 构建框架
    • 打开终端
    • 更改位置到XCode项目的根目录: cd path/to/Project
    • 运行: carthage bootstrap --platform iOS --use-xcframeworks
    • 将添加新文件
      • Cartfile.resolved = 表示已获取/构建的框架
      • Carthage文件夹 = 包含所有构建的框架
  7. 将框架拖放到项目中: TARGETS -> General -> 框架、库...
    • 所有xcframeworks
  8. 向Info.plist添加属性
    • MGLMapboxAccessToken / 字符串 /保留空白 = 确保SDK不会崩溃
    • MGLMapboxAPIBaseURL / String / 添加url = 用于获取导航JSON的URL
    • NSLocationWhenInUseUsageDescription / String / 添加描述 = 需要地理位置权限
  9. [可选] 当应用在设备上运行并遇到问题时:将arm64添加到PROJECT -> <项目名称> -> Build Settings -> Excluded Architecture Only
  10. 以示例代码为灵感

获取帮助

  • 有bug要报告吗? 提交一个issue。如果可能,请包括Flitsmeister服务的版本、完整日志以及显示问题的项目。
  • 有功能请求吗? 提交一个issue。告诉我们功能应该做什么以及为什么你需要这个功能。

示例代码

当前没有可用的演示应用。请查看Mapbox仓库或文档中的示例,特别是分叉版本。你可以尝试提供的演示应用,你需要在项目根目录下首先运行carthage update --platform iOS --use-xc-frameworks

为了看到地图或计算路线,你需要自己的地图瓦片和方向服务。

以下代码仅供参考

import Mapbox
import VietMapDirections
import VietMapCoreNavigation
import VietMapNavigation

class ViewController: UIViewController {
    var navigationView: NavigationMapView?
    
    // Keep `RouteController` in memory (class scope),
    // otherwise location updates won't be triggered
    public var mapboxRouteController: RouteController?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let navigationView = NavigationMapView(
            frame: .zero,
            // Tile loading can take a while
            styleURL: URL(string: "your style URL here"),
            config: MNConfig())
        self.navigationView = navigationView
        view.addSubview(navigationView)
        navigationView.translatesAutoresizingMaskIntoConstraints = false
        navigationView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        navigationView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        navigationView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        navigationView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        
        let waypoints = [
            CLLocation(latitude: 52.032407, longitude: 5.580310),
            CLLocation(latitude: 51.768686, longitude: 4.6827956)
        ].map { Waypoint(location: $0) }
        
        let options = NavigationRouteOptions(waypoints: waypoints, profileIdentifier: .automobileAvoidingTraffic)
        options.shapeFormat = .polyline6
        options.distanceMeasurementSystem = .metric
        options.attributeOptions = []
        
        print("[\(type(of:self))] Calculating routes with URL: \(Directions.shared.url(forCalculating: options))")
        
        /// URL is based on the base URL in the Info.plist called `MGLMapboxAPIBaseURL`
        /// - Note: Your routing provider could be strict about the user-agent of this app before allowing the call to work
        Directions.shared.calculate(options) { (waypoints, routes, error) in
            guard let route = routes?.first else { return }
            
            let simulatedLocationManager = SimulatedLocationManager(route: route)
            simulatedLocationManager.speedMultiplier = 20
            
            let mapboxRouteController = RouteController(
                along: route,
                directions: Directions.shared,
                locationManager: simulatedLocationManager)
            self.mapboxRouteController = mapboxRouteController
            mapboxRouteController.delegate = self
            mapboxRouteController.resume()
            
            NotificationCenter.default.addObserver(self, selector: #selector(self.didPassVisualInstructionPoint(notification:)), name: .routeControllerDidPassVisualInstructionPoint, object: nil)
            NotificationCenter.default.addObserver(self, selector: #selector(self.didPassSpokenInstructionPoint(notification:)), name: .routeControllerDidPassSpokenInstructionPoint, object: nil)
            
            navigationView.showRoutes([route], legIndex: 0)
        }
    }
}

// MARK: - RouteControllerDelegate

extension ViewController: RouteControllerDelegate {
    @objc public func routeController(_ routeController: RouteController, didUpdate locations: [CLLocation]) {
        let camera = MGLMapCamera(
            lookingAtCenter: locations.first!.coordinate,
            acrossDistance: 500,
            pitch: 0,
            heading: 0
        )
        
        navigationView?.setCamera(camera, animated: true)
    }
    
    @objc func didPassVisualInstructionPoint(notification: NSNotification) {
        guard let currentVisualInstruction = currentStepProgress(from: notification)?.currentVisualInstruction else { return }
        
        print(String(
            format: "didPassVisualInstructionPoint primary text: %@ and secondary text: %@",
            String(describing: currentVisualInstruction.primaryInstruction.text),
            String(describing: currentVisualInstruction.secondaryInstruction?.text)))
    }
    
    @objc func didPassSpokenInstructionPoint(notification: NSNotification) {
        guard let currentSpokenInstruction = currentStepProgress(from: notification)?.currentSpokenInstruction else { return }
        
        print("didPassSpokenInstructionPoint text: \(currentSpokenInstruction.text)")
    }
    
    private func currentStepProgress(from notification: NSNotification) -> RouteStepProgress? {
        let routeProgress = notification.userInfo?[RouteControllerNotificationUserInfoKey.routeProgressKey] as? RouteProgress
        return routeProgress?.currentLegProgress.currentStepProgress
    }
}

许可证

代码根据MIT和ISC许可证授权。ISC许可证的功能等同于MIT许可证。