【SwiftUI】MapKitで所要時間と距離数を表示させる方法!時間と分単位に調整

この記事からわかること
- Swift UIのMapKitフレームワークの使い方
- 2地点間の経路の所要時間と距離数を表示させる方法
- 所要時間を時間と分単位に直す方法
index
[open]
\ アプリをリリースしました /
環境
- Xcode:16.0
- iOS:18.0
- Swift:5.9
- macOS:Sonoma 14.6.1
SwiftUIでMapKitフレームワークを使用して地図上に経路を表示させる方法をまとめていきたいと思います。
MapKitフレームワークの使い方やポイントが分からない方は下記リンクを参考にしてください。
前提と環境
今回はSwiftUIフレームワークを使用している場合に経路の所要時間と距離数を取得し、表示させる方法をまとめていきます。
SwiftUIでは2022年8月時点で経路を表示させる方法がなさそう(私が知らないだけかも?)なのでUiKitで経路ビューを構築してUIViewRepresentable
プロパティを使ってSwiftUIで使用できるようにしています。実装方法は下記記事を参考にしてください。またこの記事も下記記事の続きになっていますのでご注意ください。
注意:SwiftUIとUIKitのMapKitの使い方は少し異なります。今回は経路表示を実装するためにUIKitの場合の地図表示方法で進んでいきますが地図を表示するだけであればSwiftUIのMapView構造体で簡単に表示できますのでこちらの記事をご覧ください。
所要時間と距離数をSwiftUIで表示する
今回の目標は以下のように所要時間と距離数を上部に表示するビューを作成していきます。

今回の作業の流れとポイント
- ビュー構造体(UIViewRepresentableに準拠)を拡張してCoordinatorクラスを作成
- SwiftUIのビュー・ビュー構造体・Coordinatorクラスの3つにプロパティを作成
- MKRouteのプロパティから所要時間と距離数を取得してプロパティに格納
- ビュー側で表示の整形
Coordinatorクラスの作成
まずはUIViewRepresentable
プロトコルを準拠させた構造体を拡張してCoordinator
クラスを追加します。
Coordinator
クラスの中には所要時間と距離数を格納するプロパティをビュー構造体と連携できるように@Binding
を使って宣言します。イニシャライザで各プロパティに受け取った値を格納できるようにしておきます。@Binding
を使用したプロパティには名前の先頭に( _:アンダースコア)をつけないとエラーになるので注意してください。
Coordinator
クラスを定義したらインスタンス化するためのmakeCoordinatorメソッド
の定義が必要になります。その際にビュー構造体のプロパティをバインディングして渡します。(この時点ではまだ未定義です)
最初はわざわざCoordinator
クラスを実装しなくても「構造体の中にプロパティを用意すればいけるかも」と思いましたが、makeUIView
メソッドの中でプロパティを更新するかつ(@Stateかmutatingが必須)、SwiftUIのビューのプロパティともバインディングさせたいためこのような形になりました。
各構造体(クラス)にプロパティを準備する
Coordinator
クラスだけではなく、ビュー構造体(UIMapView
)とSwiftUiのビュー(ContentView
)にもプロパティを定義しておきます。
@State
と@Binding
を使い分けながら宣言しておきます。これで以下のような関係性のプロパティ構造が出来上がります。
MKRouteのプロパティから所要時間と距離数を取得
2地点間の経路の所要時間と距離数はMKRoute
のプロパティから取得できます。
MKRouteのプロパティ
定義したCoordinator
クラスのプロパティにはmakeUIView
メソッドの引数で受け取るcontext
のcoordinator
プロパティからアクセスできます。これでプロパティに格納した値が伝播し、ContentView
のプロパティからも同値を参照することができるようになりました。
各プロパティを整形する
取得した値を出力すると以下のように秒単位の時間とメートル単位の距離数になります。ユーザー視点からするとだいぶ不親切なので認識しやすい単位へと変換させる処理を実装していきます。
所要時間を時間と分に直す
秒単位の時間を分に直すには60秒(=1分)で割り算、時間に直すには3600秒(60秒×60分)で割り算すればOKです。
今回は秒数の時間を受け取った時に所要時間を返すformatTime
メソッドを自作していきます。expectedTravelTimeプロパティの初期値には-1
を与えたので初期値のままなら「経路を検索中...」、0以上の値ならその時間に応じた形式で返すようにswitch
文を使って分岐させました。
小数点以下の値を表示する際はString(format:)
イニシャライザを使用すると便利です。切り上げや切り捨てなどの丸め処理においては以下の記事を参考にしてください。
距離数をkm単位に整形する
距離数に関してはメートル単位で取得できるのでkm
にするために1000m(=1km)で割り算するだけです。
あとはSwift UIのビュー側で表示するだけです。

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。
私がSwift UI学習に使用した参考書