將 MapLibre Native SDK for iOS 與 Amazon Location Service 搭配使用 - Amazon Location Service

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

將 MapLibre Native SDK for iOS 與 Amazon Location Service 搭配使用

使用 MapLibre Native SDK for iOS 將用戶端映射內嵌至 iOS 應用程式。

MapLibre Native SDK for iOS 是基於 Mapbox GL Native 的程式庫,且與 Amazon Location Service Maps 提供的樣式和動態磚相容API。您可以整合 MapLibre Native SDK for iOS,將互動式地圖檢視與可擴展、可自訂的向量映射嵌入您的 iOS 應用程式。

本教學課程說明如何將 MapLibre Native SDK for iOS 與 Amazon Location 整合。此教學課程的範例應用程式可作為 Amazon Location Service 範例儲存庫的一部分GitHub

建置應用程式:初始化

若要初始化您的應用程式:

  1. 應用程式範本建立新的 Xcode 專案。

  2. 為其介面選取 SwiftUI

  3. 為其生命週期選取 SwiftUI 應用程式。

  4. 選取 Swift 做為其語言。

使用 Swift 套件新增 MapLibre相依性

若要將套件相依性新增至 Xcode 專案:

  1. 導覽至檔案 > Swift 套件 > 新增套件相依性

  2. 輸入儲存庫URL: https://github.com/maplibre/maplibre-gl-native-distribution

    注意

    如需 Swift 套件的詳細資訊,請參閱在 https://Apple.com 將套件相依性新增至您的應用程式

  3. 在終端機中,安裝 CocoaPods:

    sudo gem install cocoapods
  4. 導覽至應用程式的專案目錄,並使用 CocoaPods 套件管理員初始化 Podfile

    pod init
  5. 開啟 Podfile 以新增 AWSCore作為相依性:

    platform :ios, '12.0' target 'Amazon Location Service Demo' do use_frameworks! pod 'AWSCore' end
  6. 下載並安裝相依性:

    pod install --repo-update
  7. 開啟 CocoaPods 建立的 Xcode 工作區:

    xed .

建置應用程式:組態

將下列金鑰和值新增至 Info.plist 以設定應用程式:

金鑰
AWSRegion us-east-1
IdentityPoolId us-east-1:54f2ba88-9390-498d-aaa5-0d97fb7ca3bd
MapName ExampleMap

建置應用程式: ContentView 配置

若要轉譯映射,請編輯 ContentView.swift

  • 新增MapView轉譯映射的 。

  • 新增顯示屬性TextField的 。

這也會設定地圖的初始中心點。

import SwiftUI struct ContentView: View { @State private var attribution = "" var body: some View { MapView(attribution: $attribution) .centerCoordinate(.init(latitude: 49.2819, longitude: -123.1187)) .zoomLevel(12) .edgesIgnoringSafeArea(.all) .overlay( TextField("", text: $attribution) .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() } }
注意

您必須為應用程式或文件上使用的每個資料提供者提供文字標記或文字屬性。屬性字串包含在 sources.esri.attributionsources.here.attributionsource.grabmaptiles.attribution金鑰下的樣式描述符回應中。將 Amazon Location 資源與資料提供者 搭配使用時,請務必閱讀服務條款與條件

建置應用程式:請求轉換

建立名為 的新 Swift 檔案,AWSSignatureV4Delegate.swift其中包含下列類別定義,以攔截AWS請求並使用 Signature 第 4 版簽署請求。此類別的執行個體將被指派為離線儲存委派,該代表也負責在地圖檢視URLs中重寫 。

import AWSCore import Mapbox class AWSSignatureV4Delegate : NSObject, MGLOfflineStorageDelegate { 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() } class func doubleEncode(path: String) -> String? { return path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)? .addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) } func offlineStorage(_ storage: MGLOfflineStorage, urlForResourceOf kind: MGLResourceKind, with url: URL) -> URL { if url.host?.contains("amazonaws.com") != true { // not an AWS URL return url } // URL-encode spaces, etc. let keyPath = String(url.path.dropFirst()) guard let percentEncodedKeyPath = keyPath.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { print("Invalid characters in path '\(keyPath)'; unsafe to sign") return url } let endpoint = AWSEndpoint(region: region, serviceName: "geo", url: url) let requestHeaders: [String: String] = ["host": endpoint!.hostName] // sign the URL let task = AWSSignatureV4Signer .generateQueryStringForSignatureV4( withCredentialProvider: credentialsProvider, httpMethod: .GET, expireDuration: 60, endpoint: endpoint!, // workaround for https://github.com/aws-amplify/aws-sdk-ios/issues/3215 keyPath: AWSSignatureV4Delegate.doubleEncode(path: percentEncodedKeyPath), requestHeaders: requestHeaders, requestParameters: .none, signBody: true) task.waitUntilFinished() if let error = task.error as NSError? { print("Error occurred: \(error)") } if let result = task.result { var urlComponents = URLComponents(url: (result as URL), resolvingAgainstBaseURL: false)! // re-use the original path; workaround for https://github.com/aws-amplify/aws-sdk-ios/issues/3215 urlComponents.path = url.path // have Mapbox GL fetch the signed URL return (urlComponents.url)! } // fall back to an unsigned URL return url } }

建置應用程式:地圖檢視

Map View 負責初始化 執行個體AWSSignatureV4Delegate並設定基礎 MGLMapView,這會擷取資源並轉譯地圖。它也會處理將屬性字串從樣式描述符的來源傳播回 ContentView

建立名為 的新 Swift 檔案,MapView.swift其中包含下列struct定義:

import SwiftUI import AWSCore import Mapbox struct MapView: UIViewRepresentable { @Binding var attribution: String private var mapView: MGLMapView private var signingDelegate: MGLOfflineStorageDelegate init(attribution: Binding<String>) { 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 region = (regionName as NSString).aws_regionTypeValue() // MGLOfflineStorage doesn't take ownership, so this needs to be a member here signingDelegate = AWSSignatureV4Delegate(region: region, identityPoolId: identityPoolId) // register a delegate that will handle SigV4 signing MGLOfflineStorage.shared.delegate = signingDelegate mapView = MGLMapView( frame: .zero, styleURL: URL(string: "https://maps.geo.\(regionName).amazonaws.com/maps/v0/maps/\(mapName)/style-descriptor")) _attribution = attribution } func makeCoordinator() -> Coordinator { Coordinator($attribution) } class Coordinator: NSObject, MGLMapViewDelegate { var attribution: Binding<String> init(_ attribution: Binding<String>) { self.attribution = attribution } func mapView(_ mapView: MGLMapView, didFinishLoading style: MGLStyle) { let source = style.sources.first as? MGLVectorTileSource let attribution = source?.attributionInfos.first self.attribution.wrappedValue = attribution?.title.string ?? "" } } // MARK: - UIViewRepresentable protocol func makeUIView(context: UIViewRepresentableContext<MapView>) -> MGLMapView { mapView.delegate = context.coordinator mapView.logoView.isHidden = true mapView.attributionButton.isHidden = true return mapView } func updateUIView(_ uiView: MGLMapView, context: UIViewRepresentableContext<MapView>) { } // MARK: - MGLMapView proxy func centerCoordinate(_ centerCoordinate: CLLocationCoordinate2D) -> MapView { mapView.centerCoordinate = centerCoordinate return self } func zoomLevel(_ zoomLevel: Double) -> MapView { mapView.zoomLevel = zoomLevel return self } }

執行此應用程式會以您選擇的樣式顯示全螢幕地圖。此範例可作為 Amazon Location Service 範例儲存庫的一部分GitHub