ハイライト
MapKit エンジニアの Jeff が 30 分未満でボストン旅行計画アプリをゼロから構築し、MapContentBuilder クロージャと宣言型 API による SwiftUI 版 MapKit が地図統合のハードルをいかに下げるかを示しました。
主要内容
SwiftUI で地図を使うのは以前は面倒でした。UIKit 時代の MKMapView はブリッジが必要で、カスタム注釈やオーバーレイには大量のデリゲートコードが必要で、カメラ制御は領域とズームレベルを手動計算する必要がありました。
(01:42)Jeff のデモは空の SwiftUI プロジェクトから始まります。MapKit をインポートし、Map() を 1 行追加するだけで、インタラクティブな地図が表示されます。デリゲートも設定もブリッジも不要です。
(02:41)注釈コンテンツは MapContentBuilder クロージャで追加し、List に View を追加する構文とほぼ同じです。Marker は標準のバルーンアイコンを表示し、Annotation には任意の SwiftUI View を配置できます。地図は自動的に視野を調整して全コンテンツを枠内に収めます。これがデフォルト動作で、手動計算は不要です。
(04:36)地図スタイルは mapStyle 修飾子で切り替えます。標準地図はデフォルトで平面表示ですが、.standard(elevation: .realistic) を追加すると地形に実際の標高が付き、橋や湖に立体感が生まれます。衛星図やハイブリッドモードにも切り替え可能です。
(09:10)カメラ制御は MapCameraPosition 状態で実現します。automatic は地図がコンテンツを自動的に枠内に収め、region は指定領域を表示、item は特定の場所にフォーカス、userLocation はユーザー位置を追従します。ユーザーが手動で地図をドラッグすると、状態は positionedByUser になり、アプリは再配置が必要かどうかを判断できます。
(17:33)選択インタラクションは Map に selection バインディングを追加するだけです。Marker は自動的に選択アニメーションを表示します。onChange と組み合わせれば、選択時にルートを取得し、Look Around 街景プレビューを表示できます。
(21:54)オーバーレイもコンテンツビルダーで追加します。MapPolyline はルートを表示し、MapPolygon と MapCircle は領域をマークします。各オーバーレイは aboveRoads または aboveLabels レベルを指定し、地図ラベルとの重なり順を制御できます。
(23:47)地図コントロールには MapUserLocationButton、MapCompass、MapScaleView があり、mapControls 修飾子で自動レイアウトされます。通常の View として手動配置も可能で、その場合は mapScope で特定の地図インスタンスに関連付けます。
詳細
最小限の地図
import MapKit
import SwiftUI
struct ContentView: View {
var body: some View {
Map()
}
}
キーポイント:
- 1 行のコードでドラッグ、ズーム、回転に対応するインタラクティブな地図を取得
- ユーザーの位置情報認可とコンパス方向を自動処理
注釈とカスタムビューの追加
struct ContentView: View {
var body: some View {
Map {
// 標準 Marker、バルーンアイコン
Marker("Parking", coordinate: .parkingGarage)
// カスタム Annotation、任意の SwiftUI View を配置
Annotation("Custom Spot", coordinate: .customSpot) {
ZStack {
Circle().fill(.blue)
Image(systemName: "car.fill")
}
}
}
}
}
キーポイント:
Markerはシンプルな地点マーカーに適し、システムがアイコンと色を処理Annotationのクロージャ内に完全な SwiftUI ビュー階層を記述可能anchor: .bottomでビューの下端を座標に合わせ、中心ではなく下端を基準に配置
検索結果に基づく動的注釈
struct ContentView: View {
@State private var searchResults: [MKMapItem] = []
@State private var position: MapCameraPosition = .automatic
var body: some View {
Map(position: $position) {
ForEach(searchResults, id: \.self) { item in
Marker(item: item)
}
}
.onChange(of: searchResults) {
position = .automatic
}
}
func search(for query: String) {
let request = MKLocalSearch.Request()
request.naturalLanguageQuery = query
request.region = visibleRegion
MKLocalSearch(request: request).start { response, _ in
searchResults = response?.mapItems ?? []
}
}
}
キーポイント:
Marker(item:)は MKMapItem の名前、アイコン、色調を自動使用- ビーチを検索すると傘アイコン、遊び場を検索すると滑り台アイコンが表示
position = .automaticで地図が全結果を表示するよう自動ズーム- ユーザーがドラッグ後に検索する場合、手動で position をリセットして再枠付けが必要
カメラ位置の状態
@State private var position: MapCameraPosition = .region(.boston)
// 指定した領域を表示
position = .region(MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 42.36, longitude: -71.06),
span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
))
// ユーザー位置を追従し、未許可の場合は指定領域にフォールバック
position = .userLocation(fallback: .region(.boston))
// ある場所を表示し、適切なズームレベルを自動計算
position = .item(MKMapItem(placemark: MKPlacemark(coordinate: .beach)))
キーポイント:
MapCameraPositionは値型で、バインディングにより Map と双方向同期- ユーザー操作後は状態が
positionedByUserになり、アプリが検出して応答可能 onMapCameraChangeで現在の可視領域を取得し、連続更新または操作終了時のみのトリガーに対応
ルートオーバーレイ
Map {
if let route {
MapPolyline(route.polyline)
.stroke(.blue, lineWidth: 5)
}
}
// ルートを取得
func getRoute(from source: MKMapItem, to destination: MKMapItem) {
let request = MKDirections.Request()
request.source = source
request.destination = destination
MKDirections(request: request).calculate { response, _ in
route = response?.routes.first
}
}
キーポイント:
MapPolylineはMKPolylineを直接受け取り、座標変換は不要StrokeStyleは破線、グラデーションなどに対応MapPolygonとMapCircleは領域をマーク。aboveRoads/aboveLabelsで道路・ラベルとの重なり順を制御。aboveRoadsは地図ラベルがオーバーレイの上に、aboveLabelsはオーバーレイがラベルの上に表示
地図コントロール
Map {
// コンテンツ
}
.mapControls {
MapUserLocationButton()
MapCompass()
MapScaleView()
}
キーポイント:
mapControlsはコントロールを適切な位置に自動レイアウト- 手動配置時は
mapScopeで関連付け:.mapScope(mapScope) - macOS には追加で
MapZoomStepperとMapPitchSliderが提供
重要ポイント
-
ローカルライフスタイルアプリにインタラクティブな地図を追加する:レストラン、ホテル、イベント系アプリは MapKit for SwiftUI で「近くのおすすめ」機能を素早く実装できます。Marker はカテゴリアイコンを自動表示し、Look Around で街景プレビューを提供。ユーザーはアプリを離れずに場所の適切さを判断できます。
-
地図でデータ可視化を行う:配送ルート、運動コース、旅行の足跡など位置情報関連データがある場合、
MapPolylineとカスタム Annotation で地図上に直接表示すればリストより直感的です。onMapCameraChangeと組み合わせれば、現在の視野内のデータポイントのみ読み込めます。 -
旅行計画ツールを作る:セッションのボストン行程計画のアプローチを参考に、検索で観光地を見つけ、Marker でマークし、ルートで接続し、Look Around でプレビュー。SwiftUI の宣言型構文により、この多段階インタラクションの実装コストが大幅に下がります。
関連セッション
- What’s new in SwiftUI — 今年の SwiftUI のアニメーション、データフロー、プレビューの改善
- Q&A: Maps technologies — MapKit、MapKit for SwiftUI、地図技術に関するエンジニア Q&A
- Meet the Presenter: Meet MapKit for SwiftUI — この MapKit for SwiftUI セッションの watch party と Q&A
コメント
GitHub Issues · utterances