Unlock the power of places with MapKit
Maps & Location 进阶 20m

用 MapKit 解锁地点能力

Unlock the power of places with MapKit

2024年6月10日

在 Apple 官方观看视频

一句话判断

Place ID 让地图上的每个 POI 有了稳定可追踪的身份标识,配合 Place Card 和 SelectionAccessory,你可以在自己应用里复刻 Apple Maps 的地点详情体验——所有数据由 Apple 维护,你不需要自己建 POI 数据库。

这场 Session 讲了什么

MapKit 今年的更新围绕”地点”这个核心概念展开,三个关键词:引用、展示、搜索。

Place ID 是一个全新的标识符体系。Apple Maps 里的每个地点(餐厅、博物馆、公园、学校等)都有一个唯一 ID,这个 ID 持久有效,Apple 更新地点数据时(比如修改了营业时间或网址),你通过 ID 查到的信息会自动同步。这意味着你可以在自己的后端数据库里用 Place ID 做主键,不再需要存储经纬度这种会过时的坐标数据。

展示层面,MapKit 把 Apple Maps 的 Place Card 能力开放给了第三方应用。通过 SelectionAccessory API,用户点击地图标注后可以弹出和系统地图一样风格的地点详情卡片,包含营业时间、电话、地址等完整信息。支持的展示模式包括全屏、紧凑和跳转 Maps 应用三种。

搜索 API 也有增强,虽然 Session 没有展开太多细节,但配合 Place ID,搜索结果现在可以直接关联到稳定的地点实体。

值得深挖的点

Place ID 的数据契约

Place ID 解决了一个长期痛点:地图数据的不一致性。以前你在应用里存储一个 POI,通常用经纬度或者地名做标识。但经纬度可能因地图数据修正而偏移,地名更是会因为同一个地点有多条记录而混乱。Place ID 是 Apple 为每个 POI 分配的全局唯一标识,而且”设计上会和地点本身一样持久”。

这个承诺的分量很重。它意味着你可以放心地把 Place ID 存进数据库、写进 URL、甚至跨平台共享(native 和 MapKit JS 使用同一套 ID)。Apple 负责维护数据的准确性,你只需要引用。如果 Apple 的编辑团队修正了一个地点的位置,你的应用自动受益——不需要发版更新。

Place ID 的获取途径也很丰富:Search API、Geocoding API 都能返回,Apple 还提供了一个 Place ID Lookup 网页工具,让你直接搜索并复制 ID,适合初期配置少量固定地点的场景。

SelectionAccessory 的三种展示策略

SelectionAccessory 支付三种风格:full(全屏详情页)、compact(紧凑卡片)和 automatic(让 MapKit 根据平台和地图尺寸自动选择)。这个设计体现了一个好产品思路:大部分开发者不应该纠结”这个 UI 该多大”,系统比你更懂。

full 模式适合地图是页面核心的场景,比如一个城市指南应用。compact 模式适合地图只是辅助信息的场景,比如一个外卖应用的配送范围预览。automatic 则是最好的默认选择——它会根据 MapView 的实际尺寸智能切换。

更灵活的是,MapItemDetail 和 PlaceDetail API 允许你在没有地图视图的情况下也能展示地点信息。比如一个列表页里点击某个餐厅,直接弹出它的 Place Card,不需要先打开地图。这让”地点信息展示”和”地图展示”彻底解耦了。

代码片段

用 Place ID 获取并展示地点

// 通过 Place ID 创建标识符,然后获取 MKMapItem
let placeID = "XXXXXXXXXX" // 从 Lookup 工具或 Search API 获得
let identifier = MKMapItem.Identifier(placeID: placeID)
let request = MKMapItem.FetchRequest(id: identifier)

if let mapItem = try? await request.mapItem {
    // 直接在地图上标注,Apple 维护的数据自动生效
    let annotation = MKMapItemAnnotation(mapItem: mapItem)
    mapView.addAnnotation(annotation)
}

场景:在应用里展示固定的地点集合(比如连锁店列表)。坑:Place ID 是字符串格式,没有类型校验,写错了不会编译报错,只有运行时返回 nil。

MapKit JS 里用 Place ID

// MapKit JS 也支持同一套 Place ID
mapkit.init({
    authorizationCallback: function(done) {
        done("你的域名专属 Token");
    }
});

// 查询地点
const place = await mapkit.Place.lookup("XXXXXXXXXX");
const annotation = new mapkit.PlaceAnnotation(place);
map.addAnnotation(annotation);

场景:在网站上展示和原生应用相同的地点数据。坑:MapKit JS 今年的 Token 机制简化了,用域名绑定的长效 Token 替代了 JWT 动态生成,别忘了迁移。

添加 Place Card 展示

// 一行代码给地图标注加上 Place Card
let selectionAccessory = MKSelectionAccessory(
    style: .automatic // full / compact / automatic
)
mapView.selectionAccessory = selectionAccessory

场景:让用户点击地图标注时弹出 Apple Maps 风格的地点详情。坑:自动模式下如果 MapView 太小,compact 模式的信息可能不够用,需要测试各种尺寸。

最佳实践

已有项目: 如果你现在用经纬度硬编码来存储地点信息,应该开始迁移到 Place ID。这是一个渐进式的工作——新添加的地点用 Place ID,老数据可以在下次更新时逐步替换。Place ID Lookup 工具很适合做小批量迁移。

新项目: 直接以 Place ID 为核心设计数据层。所有和地点相关的数据(收藏、历史、推荐)都用 Place ID 做关联键,不要存坐标。前端展示用 SelectionAccessory,除非你的设计语言需要完全自定义。

还有什么值得关注

  • MapKit JS 的 Token 机制今年彻底简化了:在开发者门户里一键生成长效 Token,绑定域名,不再需要后端动态生成 JWT。
  • MapKit JS 新增了 PlaceAnnotation 类型,专门用于展示 Place 对象,和原生 MKMapItemAnnotation 对齐。
  • MapKit JS 的初始化代码大幅减少,一个 <script> 标签加上 data-callbackdata-token 属性就搞定了。
WWDC 2024