地図表示
アプリ開発において、地図情報は最も身近で使い所のあるコンテンツです。地図をはじめ位置情報などを管理する構造体やメソッドも多数ありますので、オブジェクトを扱うという視点でも地図は非常にいい題材です。ここでは地図の基本的な扱いを学びましょう。
地図を表示する
地図関係のコンテンツは、MapKitというSwiftUIとは別のフレームワークで管理されます。
MapKitのオブジェクトは、UIをプレビュー画面に配置するというXcodeの機能が追いついていません。すべてコードで記述する必要があります。
プロジェクト作成後、ContentView.swiftを次のように編集してください。
import SwiftUI import MapKit struct ContentView: View { // JR吉祥寺駅周辺 500m @State var region = MKCoordinateRegion( center: CLLocationCoordinate2D(latitude: 35.7023137, longitude: 139.5803228), latitudinalMeters: 500, longitudinalMeters: 500) var body: some View { Map(coordinateRegion: $region) } }
最初にフレームワーク MapKit をインポートします。SwiftUIと同様にimport文でフレームワークの名前を記述すればインポートできます。
地図を表示するMap構造体は、初期化時にバインディング変数を利用します。地図を表示する前に、地図で表示する領域を管理するMKCoordinateRegion構造体で領域を定義します。
MKCoordinateRegion構造体のインスタンスを生成する書式は次の通りです。
init(center: 地図の中心, latitudinalMeters: 緯度方向の範囲(m), longitudinalMeters: 経度方向の範囲(m))
地図の中心は緯度経度で位置情報を管理するCLLocationCoordinate2D構造体で指定します。
CLLocationCoordinate2D構造体のインスタンスを生成する書式は次の通りです。
init(latitude: 緯度, longitude: 経度)
インスタンス生成時に他のオブジェクトを引数に指定する、という時点でちょっと複雑ですが、
JR吉祥寺駅(35.7023137 139.5803228)を中心とする500m範囲の範囲をMKCoordinateRegion構造体で作成すると次のように書けます。
@State var region = MKCoordinateRegion( center: CLLocationCoordinate2D(latitude: 35.7023137, longitude: 139.5803228), latitudinalMeters: 500, longitudinalMeters: 500)
このようにして作成した範囲をMapのインスタンスの引数として画面に地図を表示できます。
Map構造体の範囲を指定したインスタンスの書式は次の通りです。
Map(coordinateRegion: MKCoordinateRegion構造体)
シミュレーターを起動してアプリを実行すると、次のように地図が表示されます。
地図の範囲として 500m x 500m を指定していますが、画面上で地図を表示する領域が正方形以上であれば、指定以外の範囲も地図上に表示されます。
地図にピンを立てる
表示した地図にピンを立ててみましょう。MapKitにはピンそのものを管理するオブジェクトはありません。ピン同士を区別できることと緯度経度情報をもつ構造体を開発者自身が定義します。
struct PinItem: Identifiable { let id = UUID() let coordinate: CLLocationCoordinate2D }
サンプルでは上記のように「PinItem」の名前で構造体を定義しました。
PinItem同士が区別できるように、Identifiableプロトコルを継承し、UUIDメソッドの値でidプロパティを持ちます。7.1 リスト表示 での例と同様の構成です。
coordinateプロパティで緯度経度情報をCLLocationCoordinate2D構造体で持つようにして定義を終えます。
作成したPinItemで吉祥寺ヨドバシと吉祥寺ヤマダ電機の位置情報を地図上にピンで表示します。
struct ContentView: View { // JR吉祥寺駅周辺 500m @State var region = MKCoordinateRegion( center: CLLocationCoordinate2D(latitude: 35.7023137, longitude: 139.5803228), latitudinalMeters: 500, longitudinalMeters: 500) @State var annotations = [ // 吉祥寺ヨドバシ PinItem(coordinate: CLLocationCoordinate2D(latitude: 35.7047018, longitude: 139.581544)), // 吉祥寺ヤマダ電機 PinItem(coordinate: CLLocationCoordinate2D(latitude: 35.7023873, longitude: 139.5808619)) ] var body: some View { Map(coordinateRegion: $region, annotationItems: annotations, annotationContent: { item in MapMarker(coordinate: item.coordinate) }) } }
ピンを表示するオブジェクトとして、「annotations」という名前で吉祥寺ヨドバシと吉祥寺ヤマダ電機のPinItemオブジェクトを配列で定義します。
定義したannotationsをMapのインスタンス引数として地図上にピンを表示します。
ピンを表示する時のMap構造体の書式は次の通りです。
Map(coordinateRegion: 地図表示範囲, annotationItems: ピン情報の配列, annotationContent: { ピン情報の配列の要素 in MapMarker(coordinate: ピン情報の位置情報) } )
地図の表示範囲に加えて、ピン情報の配列を指定します。さらにピン情報の配列の処理も同時に指定します。ピン情報の処理は、配列の要素を処理するブロックの書式で記述します。
地図上のピンは、MapMaker構造体を緯度経度情報を引数にインスタンスを生成することで表示できます。
シミュレーターを起動してアプリを実行すると、次のように地図上にピンが表示されることがわかります。
地図とピンを表示するときにも、配列、Identifiableプロトコル、配列の各要素のブロック処理などリストや選択肢と似た処理もあったと思います。
地図表示では、オブジェクト同士の関連性の他に、Swiftで共通して行える処理についても学ぶことができます。