Amazon Location Service로 iOS용 MapLibre Native SDK 사용 - Amazon Location Service

Amazon Location Service로 iOS용 MapLibre Native SDK 사용

iOS용 MapLibre Native SDK를 사용하여 클라이언트측 맵을 iOS 애플리케이션에 포함할 수 있습니다.

iOS용 MapLibre Native SDK는 Mapbox GL Native를 기반으로 하는 라이브러리로, Amazon Location Service Maps API에서 제공하는 스타일 및 타일과 호환됩니다. iOS용 MapLibre Native SDK를 통합하여 확장 가능하고 사용자 정의 가능한 벡터 맵이 있는 대화형 맵 보기를 iOS 애플리케이션에 포함시킬 수 있습니다.

이 튜토리얼에서는 iOS용 MapLibre Native SDK를 Amazon Location과 통합하는 방법을 설명합니다. 이 튜토리얼의 샘플 애플리케이션은 GitHub의 Amazon Location Service 샘플 리포지토리의 일부로 제공됩니다.

애플리케이션 빌드: 초기화

애플리케이션을 초기화하려면:

  1. 템플릿에서 새 Xcode 프로젝트를 생성합니다.

  2. 인터페이스로 SwiftUI를 선택합니다.

  3. 수명 주기로 SwiftUI 애플리케이션을 선택합니다.

  4. 해당 언어로 Swift를 선택합니다.

Swift 패키지를 사용하여 MapLibre 종속성 추가

Xcode 프로젝트에 패키지 종속성을 추가하려면:

  1. 파일 > Swift 패키지 > 패키지 종속성 추가로 이동합니다.

  2. 다음 리포지토리 URL을 입력합니다. https://github.com/maplibre/maplibre-gl-native-distribution

    참고

    Swift 패키지에 대한 자세한 내용은 Apple.com에서 Adding Package Dependencies to Your App 항목을 참조하세요.

  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.attribution, sources.here.attribution, source.grabmaptiles.attribution 키의 스타일 설명자 응답에 포함됩니다. 데이터 공급자와 함께 Amazon Location 리소스를 사용할 때는 서비스 이용 약관을 반드시 읽어보세요.

애플리케이션 빌드: 변환 요청

다음 클래스 정의가 포함된 이름이 AWSSignatureV4Delegate.swift인 새 Swift 파일을 생성하여 AWS 요청을 가로채고 Signature Version 4를 사용하여 서명합니다. 이 클래스의 인스턴스는 맵 보기에서 URL 재작성도 담당하는 오프라인 스토리지 대리자로 할당됩니다.

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 } }

애플리케이션 빌드: 맵 보기

맵 보기는 AWSSignatureV4Delegate 인스턴스를 초기화하고, 리소스를 가져오고 맵을 렌더링하는 기본 MGLMapView 구성을 담당합니다. 또한 스타일 설명자 소스에서 속성 문자열을 다시 ContentView로 전파되는 것도 처리합니다.

다음 MapView.swift 정의를 포함하는 struct라는 이름을 가진 새 Swift 파일을 생성합니다.

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 } }

이 애플리케이션을 실행하면 선택한 스타일로 전체 화면 맵이 표시됩니다. 이 샘플은 GitHub의 Amazon Location Service 샘플 리포지토리의 일부로 제공됩니다.