ハイライト
MapKit の今年のアップデートは「場所」という核心概念を軸に展開され、3 つのキーワードは参照、表示、検索です。
主要内容
これまで app 内で場所データを扱う際、開発者が保存できたのは緯度経度だけでした。問題は座標が古くなることです——Apple Maps の編集により場所の位置がいつでも修正される可能性があり、app 内の古い座標は誤りになります。営業時間や電話番号などの情報も継続的に変わるため、ハードコードでは追いつけません。
今年 MapKit は Place ID 体系を導入してこの問題を解決します。Apple Maps 内の各場所(レストラン、博物館、公園、学校など)には一意で永続的な識別子があります。Place ID を主キーとしてデータベースに保存し、次回 ID でクエリすると Apple が最新メンテナンスしているデータ(更新された位置、Web サイト、営業時間を含む)が取得できます。識別子はネイティブと Web で共通、永続化でき、クロスプラットフォームで共有できます(01:01)。
表示面では、MapKit が Apple Maps の Place Card 機能をサードパーティに開放しました。SelectionAccessory API により、ユーザーが地図の注釈をタップするとシステム Maps と同じスタイルの場所詳細カードが表示され、全画面、コンパクト、Maps で開くの 3 つの表示モードをサポートします(06:30)。ページに地図ビューがなくても、MapItemDetail と PlaceDetail で場所情報を独立してレンダリングでき、UIKit / AppKit / SwiftUI それぞれに対応 API があります。Web 側では Maps Embed API が新たに追加され、JavaScript を書かずに Place Card 付きの地図を埋め込めます。
検索 API も同時に強化されました。AddressFilter で都市や郵便番号などの住所タイプのみに検索を限定でき、RegionPriority で結果を指定エリア内に強制できます。サーバー API にはページネーションも追加されました(12:12)。
詳細
Place ID:座標の代わりに識別子を使う
Place ID を取得する方法は 2 つあります。既存の Search / Geocoding API を使うか、Apple が新たに提供する Place ID Lookup ツールで一括検索します。Lookup ツールは developer.apple.com/maps の Resources ページにあり、検索と地図クリックの 2 つの操作をサポートします(02:30)。
ID を取得したら、Swift 側で MKMapItemRequest 経由で MKMapItem を非同期取得します(03:06):
struct PlaceMapView: View {
var placeID: String // "I63802885C8189B2B"
@State private var item: MKMapItem?
var body: some View {
Map {
if let item {
Marker(item: item)
}
}
.task {
guard let identifier = MKMapItem.Identifier(
rawValue: placeID
) else {
return
}
let request = MKMapItemRequest(
mapItemIdentifier: identifier
)
item = try? await request.mapItem
}
}
}
キーポイント:
MKMapItem.Identifier(rawValue:)で Place ID 文字列を型安全な識別子に変換MKMapItemRequestで非同期リクエストを開始し、Apple サーバーから最新の場所データを取得Marker(item:)で直接レンダリングし、座標を手動設定する必要なし——位置は Apple データが駆動- Apple Maps の編集で場所の位置が修正されても、Place ID を使う app はコード変更なしで変更を自動継承
Web 側の対応 API は mapkit.PlaceLookup(03:44)で、同じ Place ID で Place オブジェクトを取得後、PlaceAnnotation で注釈をレンダリングします。Token も今年簡素化され、新しい token provisioning ツールはドメイン紐付けの静的文字列を生成し、動的 JWT 生成が不要になり、手動で失効するまで期限切れになりません(04:46)。
SelectionAccessory:地図上に Place Card を表示
地図上の注釈に Place Card を追加するには、SwiftUI では modifier 1 つで済みます(07:32):
struct VisitedStoresView: View {
var visitedStores: [MKMapItem]
@State private var selection: MKMapItem?
var body: some View {
Map(selection: $selection) {
ForEach(visitedStores, id: \.self) { store in
Marker(item: store)
}
.mapItemDetailSelectionAccessory()
}
}
}
キーポイント:
mapItemDetailSelectionAccessory()はデフォルトで automatic モードを使用し、MapKit がプラットフォームと地図サイズに応じて全画面またはコンパクト表示を選択.calloutを渡すと吹き出しスタイルを強制
より実用的なシナリオ:地図上のすべての POI で Place Card を有効にし、自分の注釈だけでなく任意の POI に対応(11:17):
struct VisitedStoresView: View {
var visitedStores: [MKMapItem]
@State private var selection: MapSelection<MKMapItem>?
var body: some View {
Map(selection: $selection) {
ForEach(visitedStores, id: \.self) { store in
Marker(item: store)
.tag(MapSelection(store))
}
.mapItemDetailSelectionAccessory(.callout)
}
.mapFeatureSelectionAccessory(.callout)
}
}
キーポイント:
MapSelection<MKMapItem>は統一された選択タイプで、カスタム注釈と地図上の POI の両方をサポート.mapFeatureSelectionAccessory(.callout)により、ユーザーが地図上の任意の POI をタップして Place Card を表示可能- ユーザーが注釈周辺の公園やレストランなどを探索する際、直接コンテキスト情報を取得
地図ビューがないシナリオでは、mapItemDetailSheet(item:) で List 内に Place Card を表示(09:15):
struct StoreList: View {
var stores: [MKMapItem]
@State private var selectedStore: MKMapItem?
var body: some View {
List(
stores,
id: \.self,
selection: $selectedStore
) {
Text($0.name ?? "Apple Store")
}
.mapItemDetailSheet(item: $selectedStore)
}
}
キーポイント:
mapItemDetailSheetは地図コンテキスト外で Place Card を表示し、UIKit / AppKit / SwiftUI をサポート- Web 側の同等 API は
mapkit.PlaceDetailで、mapkit.PlaceSelectionAccessoryと併用
検索の強化:AddressFilter と RegionPriority
「Cupertino」を検索したいが同名の店舗にマッチしたくない場合、AddressFilter で都市のみに限定(14:41):
struct CoffeeMap: View {
@State private var position: MapCameraPosition = .automatic
@State private var coffeeShops: [MKMapItem] = []
var body: some View {
Map(position: $position) {
ForEach(coffeeShops, id: \.self) { café in
Marker(item: cafe)
}
}
.task {
guard let cupertino = await findCity() else {
return
}
coffeeShops = await findCoffee(in: cupertino)
}
}
private func findCity() async -> MKMapItem? {
let request = MKLocalSearch.Request()
request.naturalLanguageQuery = "cupertino"
request.addressFilter = MKAddressFilter(
including: .locality
)
let search = MKLocalSearch(request: request)
let response = try? await search.start()
return response?.mapItems.first
}
private func findCoffee(in city: MKMapItem ) async -> [MKMapItem] {
let request = MKLocalSearch.Request()
request.naturalLanguageQuery = "coffee"
let downtown = MKCoordinateRegion(
center: city.placemark.coordinate,
span: .init(
latitudeDelta: 0.01,
longitudeDelta: 0.01
)
)
request.region = downtown
request.regionPriority = .required
let search = MKLocalSearch(request: request)
let response = try? await search.start()
return response?.mapItems ?? []
}
}
キーポイント:
MKAddressFilter(including: .locality)は都市レベルの結果のみを返し、同名店舗をフィルタrequest.regionPriority = .requiredで検索結果を指定エリア内に強制し、地図をズームしても遠方の注釈が表示されない- 検索は音楽会場、スケートパーク、城、川や山などの自然地形など、より多くの場所タイプをサポート(12:18)
- Web 側は
mapkit.AddressFilter.including([mapkit.AddressCategory.Locality])とmapkit.Search.RegionPriority.Requiredに対応
重要ポイント
-
やること:データベースの緯度経度フィールドを Place ID に置き換える。価値がある理由:座標は古くなるデータ——Apple Maps の編集で位置が修正されると、ハードコードされた座標は誤りになる。Place ID は安定した参照で、クエリ時に常に Apple が最新メンテナンスしている情報を取得できる。始め方:新規追加の場所は直接 Place ID を保存。既存データは Place ID Lookup ツールでバッチ移行。
-
やること:地図に
.mapFeatureSelectionAccessory(.callout)を追加する。価値がある理由:ユーザーが地図上の任意の POI をタップして Place Card を見られ、周辺のコンテキスト(公園、レストランなど)を取得できる。探索型 app に非常に価値が高く、1 行のコードで済む。始め方:既存のMapビューにこの modifier を追加するだけで、注釈ロジックの変更は不要。 -
やること:検索で AddressFilter + RegionPriority を組み合わせる。価値がある理由:「Cupertino」検索で同名店舗のノイズ結果を回避。地図をズームした後に遠方の注釈が視野を汚染するのを防ぐ。始め方:都市検索に
addressFilter: .locality、エリア検索にregionPriority: .requiredを追加。各 1 行。 -
やること:Maps Embed API で Web ページに場所情報を表示する。価値がある理由:JavaScript 不要——Apple Developer サイトの Create a Map ツールで Place ID と token を設定し、生成された HTML スニペットをコピーするだけ。単一場所の表示シナリオに最適。始め方:developer.apple.com/maps → Resources → Create a Map で Web Embed モードを選択。
関連セッション
- What’s new in location authorization — 位置情報の認可メカニズムが大幅アップグレード。MapKit の位置情報機能と併用
- Bring context to today’s weather — WeatherKit に履歴比較と期間サマリーが追加。地図シナリオと自然に組み合わせ可能
- What’s new in AppKit — macOS でも MapKit Place Card のレンダリングをサポート
- Optimize for the spatial web — Safari と Web 技術のアップデート。MapKit JS は Web エコシステムの一部
コメント
GitHub Issues · utterances