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

Swift中Mapbox Maps包编译报错:找不到ResourceOptions

解决Mapbox中“Cannot find 'ResourceOptions' in scope”编译错误

问题说明

使用Swift和Mapbox Navigation SDK开发时,代码编译失败,提示“Cannot find 'ResourceOptions' in scope”,已检查包安装和依赖配置但未解决问题。

核心原因及解决方案

1. 缺失必要框架导入

ResourceOptions 属于 MapboxCoreNavigation 模块,而非当前导入的MapboxMaps。需在代码开头补充导入:

import MapboxCoreNavigation

2. 依赖版本不兼容

需确认Mapbox相关包版本是否匹配:

  • 保证MapboxMaps与MapboxCoreNavigation版本一致,避免跨版本API差异
  • 使用Swift Package Manager时,检查包的版本约束是否为官方推荐的兼容组合

3. 简化初始化逻辑(适配新版SDK)

部分新版Mapbox SDK已支持直接在MapInitOptions中传入accessToken,无需手动创建ResourceOptions,可替换为:

let mapInitOptions = MapInitOptions(accessToken: accessToken, styleURI: .streets)
mapView = MapView(frame: view.bounds, mapInitOptions: mapInitOptions)

4. 清理Xcode缓存

缓存可能导致依赖识别异常,执行以下操作:

  • 清理项目:按下Command + Shift + K
  • 删除DerivedData:前往~/Library/Developer/Xcode/DerivedData删除对应项目文件夹
  • 重启Xcode后重新构建

修改后的完整代码示例

import UIKit
import MapboxMaps
import MapboxCoreNavigation // 添加必要导入

/// 管理Mapbox地图标注的视图控制器
class AnnotationsMapViewController: UIViewController {
    /// Mapbox地图视图
    var mapView: MapView!
    
    /// 管理地图标注的视图模型
    var viewModel: AnnotationsMapViewModel?
    
    /// 视图加载完成后调用
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 填入你的Mapbox访问令牌
        let accessToken = "Put Access Token Here"
        
        // 方案1:使用ResourceOptions(需导入MapboxCoreNavigation)
        let resourceOptions = ResourceOptions(accessToken: accessToken)
        let mapInitOptions = MapInitOptions(resourceOptions: resourceOptions, styleURI: .streets)
        
        // 方案2:直接传入accessToken(无需手动创建ResourceOptions)
        // let mapInitOptions = MapInitOptions(accessToken: accessToken, styleURI: .streets)
        
        // 初始化地图视图
        mapView = MapView(frame: view.bounds, mapInitOptions: mapInitOptions)
        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(mapView)
        
        // 地图样式加载完成后配置标注管理器
        mapView.mapboxMap.onNext(event: .styleLoaded) { [weak self] _ in
            guard let self = self else { return }
            self.setupAnnotationManagers()
            self.updateAnnotations()
            self.setupGestureRecognizers()
        }
    }
    
    // MARK: - 配置标注管理器
    /**
     配置点标注和折线标注的管理器
     
     若管理器未初始化,则创建实例,并打印初始化状态到控制台
     */
    private func setupAnnotationManagers() {
        guard let mapView = mapView else { return }
        
        if viewModel?.pointAnnotationManager == nil {
            viewModel?.pointAnnotationManager = mapView.annotations.makePointAnnotationManager()
            print("***** PointAnnotationManager初始化完成: \(viewModel?.pointAnnotationManager != nil)")
        }
        
        if viewModel?.polylineAnnotationManager == nil {
            viewModel?.polylineAnnotationManager = mapView.annotations.makePolylineAnnotationManager()
            print("***** PolylineAnnotationManager初始化完成: \(viewModel?.polylineAnnotationManager != nil)")
        }
    }
    
    // MARK: - 更新标注
    /**
     通过点标注管理器更新地图上的标注
     
     从视图模型获取标注数据并设置到管理器,同时调用视图模型的折线更新方法
     */
    func updateAnnotations() {
        guard let viewModel = viewModel else { return }
        
        viewModel.pointAnnotationManager?.annotations = viewModel.annotations
        viewModel.updatePolylines() // 确保调用此方法应用更新
    }
    
    // MARK: - 配置手势识别器
    /**
     配置用于处理标注选择的手势识别器
     
     给地图视图添加点击手势,触发标注点击处理方法
     */
    private func setupGestureRecognizers() {
        guard let mapView = mapView else { return }
        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleAnnotationTap(_:)))
        mapView.addGestureRecognizer(tapGestureRecognizer)
    }
    
    // MARK: - 处理标注点击
    /**
     处理标注的点击手势
     
     查询点击位置的渲染特征,识别并选择对应的标注或折线;若未找到匹配项,则取消折线选中状态
     
     - Parameter sender: 点击手势识别器
     */
    @objc private func handleAnnotationTap(_ sender: UITapGestureRecognizer) {
        guard let mapView = mapView, let viewModel = viewModel else { return }
        let point = sender.location(in: mapView)
        
        // 调整点击检测的缓冲范围
        let buffer: CGFloat = 1.0 // 屏幕点单位的缓冲大小
        let hitbox = CGRect(x: point.x - buffer, y: point.y - buffer, width: 2 * buffer, height: 2 * buffer) // 使用检测范围
        
        // 查询检测范围内的渲染特征
        let options = RenderedQueryOptions(layerIds: ["annotations-layer"], filter: nil)
        mapView.mapboxMap.queryRenderedFeatures(in: hitbox, options: options) { result in
            switch result {
            case .success(let features):
                print("***** 检测到特征数量: \(features.count)")
                for feature in features {
                    if let userInfo = feature.feature.properties?["userInfo"] as? Turf.JSONValue,
                       case let .object(annotationInfo) = userInfo,
                       let annotationIdValue = annotationInfo["annotation-id"],
                       case let .string(annotationId) = annotationIdValue {
                        if let selectedAnnotation = viewModel.annotations.first(where: { ($0.userInfo?["annotation-id"] as? String) == annotationId }) {
                            viewModel.selectAnnotation(selectedAnnotation)
                            print("***** 选中标注ID: \(annotationId)")
                            return
                        }
                        if let selectedPolyline = viewModel.polylines.first(where: { ($0.userInfo?["annotation-id"] as? String) == annotationId }) {
                            viewModel.selectPolyline(selectedPolyline)
                            print("***** 选中折线ID: \(annotationId)")
                            return
                        }
                    }
                }
                // 未找到匹配标注,取消折线选中
                viewModel.deselectPolyline()
                print("***** 未找到匹配标注,取消折线选中")
            case .failure(let error):
                viewModel.deselectPolyline()
                print("***** 查询渲染特征失败: \(error)")
            }
        }
    }
    
    // MARK: - 查询渲染特征
    /**
     处理指定位置的渲染特征查询
     
     查询指定点的渲染特征,并将结果通过完成回调返回
     
     - Parameters:
       - point: 查询的屏幕点
       - options: 查询选项
       - completion: 查询结果的回调
     */
    private func queryRenderedFeatures(at point: CGPoint, options: RenderedQueryOptions, completion: @escaping (Result<[QueriedRenderedFeature], Error>) -> Void) {
        mapView.mapboxMap.queryRenderedFeatures(with: point, options: options, completion: completion)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 03:05:53