本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
使用 MapLibre Native SDK for iOS
MapLibre Native SDK for iOS 是基於 Mapbox GL Native
本教學課程說明如何將 MapLibre Native SDK for iOS 與 Amazon Location 整合。此教學課程的範例應用程式可作為 Amazon Location Service 範例儲存庫的一部分GitHub
建置應用程式:初始化
若要初始化您的應用程式:
-
從應用程式範本建立新的 Xcode 專案。
-
為其介面選取 SwiftUI。
-
為其生命週期選取 SwiftUI 應用程式。
-
選取 Swift 做為其語言。
使用 Swift 套件新增 MapLibre相依性
若要將套件相依性新增至 Xcode 專案:
-
導覽至檔案 > Swift 套件 > 新增套件相依性 。
-
輸入儲存庫URL:
https://github.com/maplibre/maplibre-gl-native-distribution
注意
如需 Swift 套件的詳細資訊,請參閱在 https://Apple.com 將套件相依性新增至您的應用程式
-
在終端機中,安裝 CocoaPods:
sudo gem install cocoapods
-
導覽至應用程式的專案目錄,並使用 CocoaPods 套件管理員初始化 Podfile:
pod init
-
開啟 Podfile 以新增
AWSCore
作為相依性:platform :ios, '12.0' target 'Amazon Location Service Demo' do use_frameworks! pod 'AWSCore' end
-
下載並安裝相依性:
pod install --repo-update
-
開啟 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()
}
}
注意
建置應用程式:請求轉換
建立名為 的新 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