通过 Amazon Location Service,把 ES 用于 iOS - Amazon Location Service

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

通过 Amazon Location Service,把 ES 用于 iOS

Tangram ES 是一个 C++ 库,用于使用 OpenGL ES 根据矢量数据渲染 2D 和 3D 地图。它是 Tangram 的原生对应部分。

使用 HERE 中的地图时,专为 Tilezen 架构而设计的 Tangram 风格在很大程度上与 Amazon Location 兼容。其中包括:

  • Bubble Wrap——功能齐全的寻路风格,带有用于显示兴趣点的有用图标

  • Cinnabar——经典外观,是普通测绘应用的首选

  • Refill——一种专为数据可视化叠加而设计的极简主义地图风格,灵感来自 Stamen Design 开创性的 Toner 风格

  • Tron——浏览 TRON 视觉语言中的比例变换

  • Walkabout——以户外为重点的风格,非常适合徒步旅行或外出旅行

本指南介绍如何使用名为 Cinnabar 的 Tangram 风格将 iOS 版 Tangram ES 与 Amazon Location 集成。此示例作为 Amazon Location Service 示例存储库的一部分提供GitHub

虽然其他 Tangram 风格最好搭配编码地形信息的栅格图块,但 Amazon Location 尚不支持此功能。

重要

以下教程中的 Tangram 样式仅与使用 VectorHereContrast 样式配置的 Amazon Location 地图资源兼容。

构建应用程序:初始化

初始化应用程序:

  1. 应用程序模板中创建新的 Xcode 项目。

  2. 选择 SwiftUI 作为其界面。

  3. 选择 SwiftUI 应用程序作为其生命周期。

  4. 选择 Swift 作为其语言。

构建应用程序:添加依赖项

要添加依赖关系,您可以使用依赖关系管理器,例如 CocoaPods

  1. 在您的终端中,安装 CocoaPods:

    sudo gem install cocoapods
  2. 导航到应用程序的项目目录并使用 CocoaPods包管理器初始化 Podfile

    pod init
  3. 打开 Podfile,以添加 AWSCoreTangram-es 作为依赖项:

    platform :ios, '12.0' target 'Amazon Location Service Demo' do use_frameworks! pod 'AWSCore' pod 'Tangram-es' end
  4. 下载并安装依赖项:

    pod install --repo-update
  5. 打开 CocoaPods 创建以下内容的 Xcode 工作区:

    xed .

构建应用程序:配置

将以下键和值添加到 Info.plist 以配置应用程序并禁用遥测:

AWSRegion us-east-1
IdentityPoolId us-east-1:54f2ba88-9390-498d-aaa5-0d97fb7ca3bd
MapName ExampleMap
SceneURL https://www.nextzen.org/carto/cinnabar-style/9/cinnabar-style.zip

构建应用程序: ContentView 布局

要渲染地图,请编辑 ContentView.swift

  • 添加渲染地图的 MapView

  • 添加显示属性的 TextField

这还会设置地图的初始中心点。

注意

您必须在应用程序或文档中为使用的每个数据提供程序提供文字标记或文本属性。属性字符串包含在样式描述符响应中的 sources.esri.attributionsources.here.attributionsource.grabmaptiles.attribution 键下。在数据提供程序处使用 Amazon Location 资源时,请务必阅读服务条款和条件

import SwiftUI import TangramMap struct ContentView: View { var body: some View { MapView() .cameraPosition(TGCameraPosition( center: CLLocationCoordinate2DMake(49.2819, -123.1187), zoom: 10, bearing: 0, pitch: 0)) .edgesIgnoringSafeArea(.all) .overlay( Text("© 2020 HERE") .disabled(true) .font(.system(size: 12, weight: .light, design: .default)) .foregroundColor(.black) .background(Color.init(Color.RGBColorSpace.sRGB, white: 0.5, opacity: 0.5)) .cornerRadius(1), alignment: .bottomTrailing) } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }

构建应用程序:请求转换

创建一个名为 AWSSignatureV4URLHandler.swift 的新 Swift 文件,其中包含以下类定义,用于拦截 AWS 请求并使用 Signature Version 4 对其进行签名。这将在 Tangram MapView 中注册为 URL 处理程序。

import AWSCore import TangramMap class AWSSignatureV4URLHandler: TGDefaultURLHandler { private let region: AWSRegionType private let identityPoolId: String private let credentialsProvider: AWSCredentialsProvider init(region: AWSRegionType, identityPoolId: String) { self.region = region self.identityPoolId = identityPoolId self.credentialsProvider = AWSCognitoCredentialsProvider(regionType: region, identityPoolId: identityPoolId) super.init() } override func downloadRequestAsync(_ url: URL, completionHandler: @escaping TGDownloadCompletionHandler) -> UInt { if url.host?.contains("amazonaws.com") != true { // not an AWS URL return super.downloadRequestAsync(url, completionHandler: completionHandler) } // URL-encode spaces, etc. let keyPath = String(url.path.dropFirst()) guard let keyPathSafe = keyPath.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { print("Invalid characters in path '\(keyPath)'; unsafe to sign") return super.downloadRequestAsync(url, completionHandler: completionHandler) } // sign the URL let endpoint = AWSEndpoint(region: region, serviceName: "geo", url: url) let requestHeaders: [String: String] = ["host": endpoint!.hostName] let task = AWSSignatureV4Signer .generateQueryStringForSignatureV4( withCredentialProvider: credentialsProvider, httpMethod: .GET, expireDuration: 60, endpoint: endpoint!, keyPath: keyPathSafe, requestHeaders: requestHeaders, requestParameters: .none, signBody: true) task.waitUntilFinished() if let error = task.error as NSError? { print("Error occurred: \(error)") } if let result = task.result { // have Tangram fetch the signed URL return super.downloadRequestAsync(result as URL, completionHandler: completionHandler) } // fall back to an unsigned URL return super.downloadRequestAsync(url, completionHandler: completionHandler) } }

构建应用程序:地图视图

地图视图负责初始化实例 AWSSignatureV4Delegate 和配置底层 MGLMapView,底层视图获取资源并渲染地图。它还处理将属性字符串从样式描述符的来源传播回 ContentView

创建一个名为 MapView.swift 的新 Swift 文件,其中包含以下 struct 定义:

import AWSCore import TangramMap import SwiftUI struct MapView: UIViewRepresentable { private let mapView: TGMapView init() { let regionName = Bundle.main.object(forInfoDictionaryKey: "AWSRegion") as! String let identityPoolId = Bundle.main.object(forInfoDictionaryKey: "IdentityPoolId") as! String let mapName = Bundle.main.object(forInfoDictionaryKey: "MapName") as! String let sceneURL = URL(string: Bundle.main.object(forInfoDictionaryKey: "SceneURL") as! String)! let region = (regionName as NSString).aws_regionTypeValue() // rewrite tile URLs to point at AWS resources let sceneUpdates = [ TGSceneUpdate(path: "sources.mapzen.url", value: "https://maps.geo.\(regionName).amazonaws.com/maps/v0/maps/\(mapName)/tiles/{z}/{x}/{y}")] // instantiate a TGURLHandler that will sign AWS requests let urlHandler = AWSSignatureV4URLHandler(region: region, identityPoolId: identityPoolId) // instantiate the map view and attach the URL handler mapView = TGMapView(frame: .zero, urlHandler: urlHandler) // load the map style and apply scene updates (properties modified at runtime) mapView.loadScene(from: sceneURL, with: sceneUpdates) } func cameraPosition(_ cameraPosition: TGCameraPosition) -> MapView { mapView.cameraPosition = cameraPosition return self } // MARK: - UIViewRepresentable protocol func makeUIView(context: Context) -> TGMapView { return mapView } func updateUIView(_ uiView: TGMapView, context: Context) { } }

运行此应用程序会以您选择的样式显示全屏地图。此示例作为 Amazon Location Service 示例存储库的一部分提供GitHub