TechSwiftUIJapanese

[ SwiftUI ][ Mapbox ] iOS アプリ で Mapbox 地図に マーカー ピン を立てる

eye-catch Tech

関連する 前回の記事で SwiftUI を使って iOS 上に Mapbox の地図を表示することができたので、次の ステップ として地図に マーカー (ピン) を立てて、特定の地点を指し示すようにしてみたいと思います。

Xcode: 13.2.1
iOS: 15.2
Swift: 5.5
mapbox-maps-ios: v10.2.0

Mapbox 公式 ドキュメント の説明

Mapbox 公式 ドキュメント には Example として、以下のように コペンハーゲン に マーカー を表示する サンプル が掲載されています。まずは、その サンプル の内容を確認していくことにします。

引用元: https://docs.mapbox.com/ios/maps/examples/point-annotation/

UIViewController

前回の記事同様、 公式 サイト で提供されているのは UIViewController のものですので、 SwiftUI で扱うためには UIViewControllerRepresentable を用いる必要があります。 考え方は前回の記事と同様ですので、詳細については前回の記事を参考にしてください。

MapBox MapView の生成

サンプル で紹介されている ViewController では最初に マップ の中心を指定し、 マップ を生成しています。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-comment">// Center the map camera over Copenhagen.</span>
<span class="hljs-keyword">let</span> centerCoordinate = <span class="hljs-constructor">CLLocationCoordinate2D(<span class="hljs-params">latitude</span>: 55.665957, <span class="hljs-params">longitude</span>: 12.550343)</span>
<span class="hljs-keyword">let</span> options = <span class="hljs-constructor">MapInitOptions(<span class="hljs-params">cameraOptions</span>: CameraOptions(<span class="hljs-params">center</span>: <span class="hljs-params">centerCoordinate</span>, <span class="hljs-params">zoom</span>: 8.0)</span>)
mapView = <span class="hljs-constructor">MapView(<span class="hljs-params">frame</span>: <span class="hljs-params">view</span>.<span class="hljs-params">bounds</span>, <span class="hljs-params">mapInitOptions</span>: <span class="hljs-params">options</span>)</span>
mapView.autoresizingMask = <span class="hljs-literal">[.<span class="hljs-identifier">flexibleWidth</span>, .<span class="hljs-identifier">flexibleHeight</span>]</span>
view.add<span class="hljs-constructor">Subview(<span class="hljs-params">mapView</span>)</span>
<span class="hljs-comment">// Center the map camera over Copenhagen.</span> <span class="hljs-keyword">let</span> centerCoordinate = <span class="hljs-constructor">CLLocationCoordinate2D(<span class="hljs-params">latitude</span>: 55.665957, <span class="hljs-params">longitude</span>: 12.550343)</span> <span class="hljs-keyword">let</span> options = <span class="hljs-constructor">MapInitOptions(<span class="hljs-params">cameraOptions</span>: CameraOptions(<span class="hljs-params">center</span>: <span class="hljs-params">centerCoordinate</span>, <span class="hljs-params">zoom</span>: 8.0)</span>) mapView = <span class="hljs-constructor">MapView(<span class="hljs-params">frame</span>: <span class="hljs-params">view</span>.<span class="hljs-params">bounds</span>, <span class="hljs-params">mapInitOptions</span>: <span class="hljs-params">options</span>)</span> mapView.autoresizingMask = <span class="hljs-literal">[.<span class="hljs-identifier">flexibleWidth</span>, .<span class="hljs-identifier">flexibleHeight</span>]</span> view.add<span class="hljs-constructor">Subview(<span class="hljs-params">mapView</span>)</span>
// Center the map camera over Copenhagen.
let centerCoordinate = CLLocationCoordinate2D(latitude: 55.665957, longitude: 12.550343)
let options = MapInitOptions(cameraOptions: CameraOptions(center: centerCoordinate, zoom: 8.0))

mapView = MapView(frame: view.bounds, mapInitOptions: options)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(mapView)

ただし、このままでは マップ を表示することができないため、以下のように修正していきます。 ”Your Access Token” には有効な アクセストークン を指定してください。

  • myResourceOptions として アクセストークンをセット
  • MapInitOptions に resourceOptions パラメータ を追加
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-comment">// Set your access token</span>
<span class="hljs-keyword">let</span> myResourceOptions = <span class="hljs-constructor">ResourceOptions(<span class="hljs-params">accessToken</span>: <span class="hljs-string">"Your Access Token"</span>)</span>
<span class="hljs-comment">// Center the map camera over Copenhagen.</span>
<span class="hljs-keyword">let</span> centerCoordinate = <span class="hljs-constructor">CLLocationCoordinate2D(<span class="hljs-params">latitude</span>: 55.665957, <span class="hljs-params">longitude</span>: 12.550343)</span>
<span class="hljs-keyword">let</span> options = <span class="hljs-constructor">MapInitOptions(<span class="hljs-params">resourceOptions</span>: <span class="hljs-params">myResourceOptions</span>, <span class="hljs-params">cameraOptions</span>: CameraOptions(<span class="hljs-params">center</span>: <span class="hljs-params">centerCoordinate</span>, <span class="hljs-params">zoom</span>: 8.0)</span>)
mapView = <span class="hljs-constructor">MapView(<span class="hljs-params">frame</span>: <span class="hljs-params">view</span>.<span class="hljs-params">bounds</span>, <span class="hljs-params">mapInitOptions</span>: <span class="hljs-params">options</span>)</span>
mapView.autoresizingMask = <span class="hljs-literal">[.<span class="hljs-identifier">flexibleWidth</span>, .<span class="hljs-identifier">flexibleHeight</span>]</span>
view.add<span class="hljs-constructor">Subview(<span class="hljs-params">mapView</span>)</span>
<span class="hljs-comment">// Set your access token</span> <span class="hljs-keyword">let</span> myResourceOptions = <span class="hljs-constructor">ResourceOptions(<span class="hljs-params">accessToken</span>: <span class="hljs-string">"Your Access Token"</span>)</span> <span class="hljs-comment">// Center the map camera over Copenhagen.</span> <span class="hljs-keyword">let</span> centerCoordinate = <span class="hljs-constructor">CLLocationCoordinate2D(<span class="hljs-params">latitude</span>: 55.665957, <span class="hljs-params">longitude</span>: 12.550343)</span> <span class="hljs-keyword">let</span> options = <span class="hljs-constructor">MapInitOptions(<span class="hljs-params">resourceOptions</span>: <span class="hljs-params">myResourceOptions</span>, <span class="hljs-params">cameraOptions</span>: CameraOptions(<span class="hljs-params">center</span>: <span class="hljs-params">centerCoordinate</span>, <span class="hljs-params">zoom</span>: 8.0)</span>) mapView = <span class="hljs-constructor">MapView(<span class="hljs-params">frame</span>: <span class="hljs-params">view</span>.<span class="hljs-params">bounds</span>, <span class="hljs-params">mapInitOptions</span>: <span class="hljs-params">options</span>)</span> mapView.autoresizingMask = <span class="hljs-literal">[.<span class="hljs-identifier">flexibleWidth</span>, .<span class="hljs-identifier">flexibleHeight</span>]</span> view.add<span class="hljs-constructor">Subview(<span class="hljs-params">mapView</span>)</span>
// Set your access token
let myResourceOptions = ResourceOptions(accessToken: "Your Access Token")

// Center the map camera over Copenhagen.
let centerCoordinate = CLLocationCoordinate2D(latitude: 55.665957, longitude: 12.550343)
let options = MapInitOptions(resourceOptions: myResourceOptions, cameraOptions: CameraOptions(center: centerCoordinate, zoom: 8.0))

mapView = MapView(frame: view.bounds, mapInitOptions: options)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(mapView)

ここで、いくつか馴染みの薄そうな アイテム について補足していきます。

CLLocationCoordinate2D

CLLocationCoordinate2D は 緯度  と 経度 を パラメータ として生成する位置情報のオブジェクトです。今回の例では マップ の中心座標として利用しています。

MapInitOptions

ResourceOptions として accessToken を指定したり、 CameraOptions として 中心座標や縮尺などを指定した マップ 生成時の オプション 用 オブジェクト です。 

cameraState

MapView 生成後 サンプル では続いて以下の コード が登場します。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-comment">// We want to display the annotation at the center of the map's current viewport</span>
let centerCoordinate = mapView<span class="hljs-selector-class">.cameraState</span><span class="hljs-selector-class">.center</span>
<span class="hljs-comment">// We want to display the annotation at the center of the map's current viewport</span> let centerCoordinate = mapView<span class="hljs-selector-class">.cameraState</span><span class="hljs-selector-class">.center</span>
// We want to display the annotation at the center of the map's current viewport
let centerCoordinate = mapView.cameraState.center

中心座標を指定し マップ を生成した直後に再度中心座標を取得しているので、今回の実装においては実質的に意味はないため、 今回は コメントアウト してしまいます。

PointAnnotation, AnnotationOrchestrator

続いて サンプルコード では続いて以下の コード が登場します。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-comment">// Make a `PointAnnotationManager` which will be responsible for managing a</span>
<span class="hljs-comment">// collection of `PointAnnotation`s.</span>
<span class="hljs-keyword">let</span> pointAnnotationManager = mapView.annotations.make<span class="hljs-constructor">PointAnnotationManager()</span>
<span class="hljs-comment">// Initialize a point annotation with a single coordinate</span>
<span class="hljs-comment">// and configure it with a custom image (sourced from the asset catalogue)</span>
var customPointAnnotation = <span class="hljs-constructor">PointAnnotation(<span class="hljs-params">coordinate</span>: <span class="hljs-params">centerCoordinate</span>)</span>
<span class="hljs-comment">// Make a `PointAnnotationManager` which will be responsible for managing a</span> <span class="hljs-comment">// collection of `PointAnnotation`s.</span> <span class="hljs-keyword">let</span> pointAnnotationManager = mapView.annotations.make<span class="hljs-constructor">PointAnnotationManager()</span> <span class="hljs-comment">// Initialize a point annotation with a single coordinate</span> <span class="hljs-comment">// and configure it with a custom image (sourced from the asset catalogue)</span> var customPointAnnotation = <span class="hljs-constructor">PointAnnotation(<span class="hljs-params">coordinate</span>: <span class="hljs-params">centerCoordinate</span>)</span>
// Make a `PointAnnotationManager` which will be responsible for managing a
// collection of `PointAnnotation`s.
let pointAnnotationManager = mapView.annotations.makePointAnnotationManager()

// Initialize a point annotation with a single coordinate
// and configure it with a custom image (sourced from the asset catalogue)
var customPointAnnotation = PointAnnotation(coordinate: centerCoordinate)

PointAnnotationManager, PointAnnotation という今回の トピック の肝になる オブジェクト を扱っています。 “PointAnnotationManager” という配列 を生成し、 後ほどその配列に登録する要素になる PointAnnotation を生成しています。
理解のため、それぞれ少し掘り下げてみます。

PointAnnotation

PointAnnotation とは Annotation プロトコル に準拠した構造体です。

PointAnnotation
public struct PointAnnotation : Annotation

https://docs.mapbox.com/ios/maps/api/10.2.0/Structs/PointAnnotation.html#/PointAnnotation

Annotation プロトコル の内容と共に PointAnnotation 構造体 の内容を確認してみます。
下表の通り、 PointAnnotation 構造体 は Annotation プロトコル に point プロパティ が追加されていることが分かります。

struct PointAnnotationprotocol Annotation
idid
geometrygeometry
point
userInfouserInfo
Property comparison PointAnnotation vs Annotation

Annotation
public protocol Annotation

https://docs.mapbox.com/ios/maps/api/10.2.0/Protocols/Annotation.html#/Annotation

つまり、 geometry (地図情報) を表現する Annotation プロトコル に point (地図上の特定地点) の表現を追加したものが PointAnnotation ということになります。 本記事の トピック でもある マーカー ピン を地図上で指定するためには、この PointAnnotation 構造体の point に マーカー ピン を立てたい座標を指定すれば良いことが分かります。

このことが理解できると、 直前に実施している PointAnnotationManager の活用方法の理解が早くなるはずです。

PointAnnotationManager

PointAnnotationManager は端的にいうと PointAnnotation の配列です。 マップ 上に複数の マーカー ピン を立てる場面を想像すれば配列を活用する メリット み見えてくると思います。

AnnotationOrchestrator

AnnotationOrchestrator は PointAnnotationManager を含む Annotation を扱う プロパティ や メソッド を定義した クラス になります。 Annotation を扱う際に活用することになります。

AnnotationOrchestrator に関連する部分の理解が深まったところで、 再度 サンプルコード の流れに戻ってみます。

生成した PointAnnotation に image パラメータを追加

PointAnnotation の生成後 サンプルコード では続いて以下の コード が登場します。 ここでは先ほど生成した PointAnnotation オブジェクト に Image Convenience を 用いて マーカー 用の画像 イメージ を指定しています。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-comment">// Make the annotation show a red pin</span>
customPointAnnotation.<span class="hljs-built_in">image</span> = .init(<span class="hljs-built_in">image</span>: UIImage(named: <span class="hljs-string">"red_pin"</span>)!, <span class="hljs-built_in">name</span>: <span class="hljs-string">"red_pin"</span>)
<span class="hljs-comment">// Make the annotation show a red pin</span> customPointAnnotation.<span class="hljs-built_in">image</span> = .init(<span class="hljs-built_in">image</span>: UIImage(named: <span class="hljs-string">"red_pin"</span>)!, <span class="hljs-built_in">name</span>: <span class="hljs-string">"red_pin"</span>)
// Make the annotation show a red pin
customPointAnnotation.image = .init(image: UIImage(named: "red_pin")!, name: "red_pin")

なお、ここで指定している “red_pin” は別途 Xcode の Assets に登録する必要があります。

register “red_pin” as Assets

画像を設定した PointAnnotation を PointAnnotationManager 配列として設定

最後に、画像を設定した PointAnnotation オブジェクト を 先ほど作成した PointAnnotationManager に設定しています。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Add <span class="hljs-keyword">the</span> annotation <span class="hljs-built_in">to</span> <span class="hljs-keyword">the</span> manager <span class="hljs-keyword">in</span> order <span class="hljs-built_in">to</span> render <span class="hljs-keyword">it</span> <span class="hljs-keyword">on</span> <span class="hljs-title">the</span> <span class="hljs-title">map</span>.
pointAnnotationManager.annotations = [customPointAnnotation]
// Add <span class="hljs-keyword">the</span> annotation <span class="hljs-built_in">to</span> <span class="hljs-keyword">the</span> manager <span class="hljs-keyword">in</span> order <span class="hljs-built_in">to</span> render <span class="hljs-keyword">it</span> <span class="hljs-keyword">on</span> <span class="hljs-title">the</span> <span class="hljs-title">map</span>. pointAnnotationManager.annotations = [customPointAnnotation]
// Add the annotation to the manager in order to render it on the map.
pointAnnotationManager.annotations = [customPointAnnotation]

こうすることで、MapView内にこの画像設定済みの PointAnnotation が配置され、マップに描画されるようになるということです。

以上で マーカー ピン を表示する準備が整いましたので、 早速実行してみたいと思います。

iOS 上で Mapbox マップ に マーカー ピン を表示

実行すると以下のようにマーカーが指定した画像で指定した地点に表示されます。


まとめ

  • MapBox の MapView に マーカー ピン を立てるためには立てたい地点を PointAnnotation 構造体で生成
  • 生成した PointAnnotation 構造体を PointAnnotationManager 配列に登録
  • マーカー 用の画像は別途 Assets に登録しておき Image Convenience で指定

関連記事

参照情報

docs.mapbox.com Add a marker to the map | Maps SDK | iOS | Mapbox

www.oreilly.com Head First Swift [Book]

docs.swift.org Protocols — The Swift Programming Language (Swift 5.5)

Mapbox マップ 表示に用いた コード

ContentView.swift

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-keyword">import</span> SwiftUI
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">ContentView</span>: <span class="hljs-title">View</span> </span>{
<span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> {
<span class="hljs-type">MapViewWrapper</span>()
}
}
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">ContentView_Previews</span>: <span class="hljs-title">PreviewProvider</span> </span>{
<span class="hljs-keyword">static</span> <span class="hljs-keyword">var</span> previews: some <span class="hljs-type">View</span> {
<span class="hljs-type">ContentView</span>()
}
}
<span class="hljs-keyword">import</span> SwiftUI <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">ContentView</span>: <span class="hljs-title">View</span> </span>{ <span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> { <span class="hljs-type">MapViewWrapper</span>() } } <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">ContentView_Previews</span>: <span class="hljs-title">PreviewProvider</span> </span>{ <span class="hljs-keyword">static</span> <span class="hljs-keyword">var</span> previews: some <span class="hljs-type">View</span> { <span class="hljs-type">ContentView</span>() } }
import SwiftUI

struct ContentView: View {
    var body: some View {
        MapViewWrapper()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

MapWithMarkerView.swift

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import SwiftUI
import MapboxMaps
<span class="hljs-keyword">struct</span> MapViewWrapper : UIViewControllerRepresentable {
func make<span class="hljs-constructor">UIViewController(<span class="hljs-params">context</span>: Context)</span> -> ViewController {
return <span class="hljs-constructor">ViewController()</span>
}
func update<span class="hljs-constructor">UIViewController(<span class="hljs-params">_</span> <span class="hljs-params">uiViewController</span>: ViewController, <span class="hljs-params">context</span>: Context)</span> {
}
}
<span class="hljs-keyword">class</span> ViewController: UIViewController {
var mapView: MapView!
override func view<span class="hljs-constructor">DidLoad()</span> {
super.view<span class="hljs-constructor">DidLoad()</span>
<span class="hljs-comment">// Set your access token</span>
<span class="hljs-keyword">let</span> myResourceOptions = <span class="hljs-constructor">ResourceOptions(<span class="hljs-params">accessToken</span>: <span class="hljs-string">"Your Access Token"</span>)</span>
<span class="hljs-comment">// Center the map camera over Copenhagen.</span>
<span class="hljs-keyword">let</span> centerCoordinate = <span class="hljs-constructor">CLLocationCoordinate2D(<span class="hljs-params">latitude</span>: 55.665957, <span class="hljs-params">longitude</span>: 12.550343)</span>
<span class="hljs-keyword">let</span> options = <span class="hljs-constructor">MapInitOptions(<span class="hljs-params">resourceOptions</span>: <span class="hljs-params">myResourceOptions</span>, <span class="hljs-params">cameraOptions</span>: CameraOptions(<span class="hljs-params">center</span>: <span class="hljs-params">centerCoordinate</span>, <span class="hljs-params">zoom</span>: 8.0)</span>)
mapView = <span class="hljs-constructor">MapView(<span class="hljs-params">frame</span>: <span class="hljs-params">view</span>.<span class="hljs-params">bounds</span>, <span class="hljs-params">mapInitOptions</span>: <span class="hljs-params">options</span>)</span>
mapView.autoresizingMask = <span class="hljs-literal">[.<span class="hljs-identifier">flexibleWidth</span>, .<span class="hljs-identifier">flexibleHeight</span>]</span>
view.add<span class="hljs-constructor">Subview(<span class="hljs-params">mapView</span>)</span>
<span class="hljs-comment">// Make a `PointAnnotationManager` which will be responsible for managing a</span>
<span class="hljs-comment">// collection of `PointAnnotation`s.</span>
<span class="hljs-keyword">let</span> pointAnnotationManager = mapView.annotations.make<span class="hljs-constructor">PointAnnotationManager()</span>
<span class="hljs-comment">// Initialize a point annotation with a single coordinate</span>
<span class="hljs-comment">// and configure it with a custom image (sourced from the asset catalogue)</span>
var customPointAnnotation = <span class="hljs-constructor">PointAnnotation(<span class="hljs-params">coordinate</span>: <span class="hljs-params">centerCoordinate</span>)</span>
<span class="hljs-comment">// Make the annotation show a red pin</span>
customPointAnnotation.image = .init(image: <span class="hljs-constructor">UIImage(<span class="hljs-params">named</span>: <span class="hljs-string">"red_pin"</span>)</span>!, name: <span class="hljs-string">"red_pin"</span>)
<span class="hljs-comment">// Add the annotation to the manager in order to render it on the map.</span>
pointAnnotationManager.annotations = <span class="hljs-literal">[<span class="hljs-identifier">customPointAnnotation</span>]</span>
}
}
import SwiftUI import MapboxMaps <span class="hljs-keyword">struct</span> MapViewWrapper : UIViewControllerRepresentable { func make<span class="hljs-constructor">UIViewController(<span class="hljs-params">context</span>: Context)</span> -> ViewController { return <span class="hljs-constructor">ViewController()</span> } func update<span class="hljs-constructor">UIViewController(<span class="hljs-params">_</span> <span class="hljs-params">uiViewController</span>: ViewController, <span class="hljs-params">context</span>: Context)</span> { } } <span class="hljs-keyword">class</span> ViewController: UIViewController { var mapView: MapView! override func view<span class="hljs-constructor">DidLoad()</span> { super.view<span class="hljs-constructor">DidLoad()</span> <span class="hljs-comment">// Set your access token</span> <span class="hljs-keyword">let</span> myResourceOptions = <span class="hljs-constructor">ResourceOptions(<span class="hljs-params">accessToken</span>: <span class="hljs-string">"Your Access Token"</span>)</span> <span class="hljs-comment">// Center the map camera over Copenhagen.</span> <span class="hljs-keyword">let</span> centerCoordinate = <span class="hljs-constructor">CLLocationCoordinate2D(<span class="hljs-params">latitude</span>: 55.665957, <span class="hljs-params">longitude</span>: 12.550343)</span> <span class="hljs-keyword">let</span> options = <span class="hljs-constructor">MapInitOptions(<span class="hljs-params">resourceOptions</span>: <span class="hljs-params">myResourceOptions</span>, <span class="hljs-params">cameraOptions</span>: CameraOptions(<span class="hljs-params">center</span>: <span class="hljs-params">centerCoordinate</span>, <span class="hljs-params">zoom</span>: 8.0)</span>) mapView = <span class="hljs-constructor">MapView(<span class="hljs-params">frame</span>: <span class="hljs-params">view</span>.<span class="hljs-params">bounds</span>, <span class="hljs-params">mapInitOptions</span>: <span class="hljs-params">options</span>)</span> mapView.autoresizingMask = <span class="hljs-literal">[.<span class="hljs-identifier">flexibleWidth</span>, .<span class="hljs-identifier">flexibleHeight</span>]</span> view.add<span class="hljs-constructor">Subview(<span class="hljs-params">mapView</span>)</span> <span class="hljs-comment">// Make a `PointAnnotationManager` which will be responsible for managing a</span> <span class="hljs-comment">// collection of `PointAnnotation`s.</span> <span class="hljs-keyword">let</span> pointAnnotationManager = mapView.annotations.make<span class="hljs-constructor">PointAnnotationManager()</span> <span class="hljs-comment">// Initialize a point annotation with a single coordinate</span> <span class="hljs-comment">// and configure it with a custom image (sourced from the asset catalogue)</span> var customPointAnnotation = <span class="hljs-constructor">PointAnnotation(<span class="hljs-params">coordinate</span>: <span class="hljs-params">centerCoordinate</span>)</span> <span class="hljs-comment">// Make the annotation show a red pin</span> customPointAnnotation.image = .init(image: <span class="hljs-constructor">UIImage(<span class="hljs-params">named</span>: <span class="hljs-string">"red_pin"</span>)</span>!, name: <span class="hljs-string">"red_pin"</span>) <span class="hljs-comment">// Add the annotation to the manager in order to render it on the map.</span> pointAnnotationManager.annotations = <span class="hljs-literal">[<span class="hljs-identifier">customPointAnnotation</span>]</span> } }
import SwiftUI
import MapboxMaps

struct MapViewWrapper : UIViewControllerRepresentable {
    
    func makeUIViewController(context: Context) -> ViewController {
        return ViewController()
    }
    
    func updateUIViewController(_ uiViewController: ViewController, context: Context) {
        
    }
}

class ViewController: UIViewController {

    var mapView: MapView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set your access token
        let myResourceOptions = ResourceOptions(accessToken: "Your Access Token")
        
        // Center the map camera over Copenhagen.
        let centerCoordinate = CLLocationCoordinate2D(latitude: 55.665957, longitude: 12.550343)
        let options = MapInitOptions(resourceOptions: myResourceOptions, cameraOptions: CameraOptions(center: centerCoordinate, zoom: 8.0))

        mapView = MapView(frame: view.bounds, mapInitOptions: options)
        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(mapView)

        // Make a `PointAnnotationManager` which will be responsible for managing a
        // collection of `PointAnnotation`s.
        let pointAnnotationManager = mapView.annotations.makePointAnnotationManager()

        // Initialize a point annotation with a single coordinate
        // and configure it with a custom image (sourced from the asset catalogue)
        var customPointAnnotation = PointAnnotation(coordinate: centerCoordinate)

        // Make the annotation show a red pin
        customPointAnnotation.image = .init(image: UIImage(named: "red_pin")!, name: "red_pin")

        // Add the annotation to the manager in order to render it on the map.
        pointAnnotationManager.annotations = [customPointAnnotation]
    }
}
Ads