Highlight
MapKit 在 iOS 26 推出 PlaceDescriptor、统一的 MKGeocodingRequest/MKReverseGeocodingRequest、骑行路线 transportType、以及 MapKit JS 的 Look Around 视图。
核心内容
很多 App 的地图体验有一个共同问题:手里只有一段地址或一组经纬度,却拿不到 Apple Maps 那套丰富的店铺数据。过去要么自己拼一个低信息量的标注,要么靠 MKLocalSearch 搜出一堆候选项再筛——CRM 同步、App Intents 之间传值、跨进程引用一个具体地点的场景里都很别扭。
今年 MapKit 引入了 PlaceDescriptor,放在新的 GeoToolbox 框架里。它允许把 commonName、地址、坐标、设备位置打包成一个结构化引用,再交给 MKMapItemRequest 解析成完整的 MKMapItem。解析出来的 MapItem 与通过 Place ID 拿到的一致,能直接显示官方名称、图标、营业时间,也能挂上 Place Card。
地理编码这次也合并了入口。MKGeocodingRequest(地址→坐标)和 MKReverseGeocodingRequest(坐标→地址)取代了 CLGeocoder 在 MapKit 场景下的位置。方向 API 加了 transportType = .cycling,第一次让骑行路径成为一等公民。MapKit JS 这边也补齐了 Look Around 的交互式视图和事件回调,网页端能直接嵌入 3D 街景。
详细内容
PlaceDescriptor 的最小构造只需要一个 representation 加一个 commonName:
// Creating and resolving a PlaceDescriptor with coordinate PlaceRepresentation
import GeoToolbox
import MapKit
let annaLiviaCoordinates = CLLocationCoordinate2D(
latitude: 53.347673,
longitude: -6.290198
)
let annaLiviaDescriptor = PlaceDescriptor(
representations: [.coordinate(annaLiviaCoordinates)],
commonName: "Anna Livia Fountain"
)
let request = MKMapItemRequest(placeDescriptor: annaLiviaDescriptor)
do {
annaLiviaMapItem = try await request.mapItem
} catch {
print("Error resolving placeDescriptor: \(error)")
}
关键点:
import GeoToolbox:PlaceDescriptor 不在 MapKit 主包里,需要单独引入新框架。representations: [.coordinate(...)]:representations 数组按精度降序排列,这里只有一个坐标。commonName:必须是公开知名的名字(如 Sydney Opera House),不要传”妈妈家”这类私有别名,对解析没有帮助。MKMapItemRequest(placeDescriptor:):异步请求 Apple Maps 后端把 descriptor 解析为 MKMapItem。try await request.mapItem:失败时抛出,需要 do/catch 兜底。
如果原始数据是地址而不是坐标,把 representation 换成 .address(05:56):
// Creating and resolving a PlaceDescriptor with address PlaceRepresentation
import GeoToolbox
import MapKit
let address = "121-122 James's St, Dublin 8"
let descriptor = PlaceDescriptor(
representations: [.address(address)],
commonName: "Obelisk Fountain"
)
let request = MKMapItemRequest(placeDescriptor: descriptor)
do {
obeliskFountain = try await request.mapItem
} catch {
print("Error resolving placeDescriptor: \(error)")
}
关键点:
.address(address):使用尽可能完整的地址字符串,包括街号、城市、邮编,命中率更高。- representations 数组顺序很重要——如果坐标是从地址反推来的,应把 address 排在前面。
- 解析逻辑由 MapKit 后端决定,调用方只需提供描述。
跨 App 传递地点时(如 App Intents),可以用 supportingRepresentations 把多家服务的 ID 一起塞进去(06:45):
// Creating a PlaceDescriptor with identifiers
import GeoToolbox
let annaLiviaCoordinates = CLLocationCoordinate2D(
latitude: 53.347673,
longitude: -6.290198
)
let identifiers = ["com.apple.MapKit" : "ICBB5FD7684CE949"]
let annaLiviaDescriptor = PlaceDescriptor(
representations: [.coordinate(annaLiviaCoordinates)],
commonName: "Anna Livia Fountain",
supportingRepresentations: [.serviceIdentifiers(identifiers)]
)
关键点:
serviceIdentifiers是字典:key 是地图服务的 bundle id(com.apple.MapKit),value 是该服务的 place id。- 如果有 MapKit 的 identifier,
MKMapItemRequest会优先使用它;解析失败再回退到坐标/地址 representation。 - 可以并列放多家服务的 id,让接收方根据自己用的 SDK 取对应字段——这就是 PlaceDescriptor 适合做 App Intents 参数的原因。
骑行路线的写法是在原本的 MKDirections.Request 上加一行 transportType(16:06):
// Fetch a cycling route
let request = MKDirections.Request()
request.source = MKMapItem.forCurrentLocation()
request.destination = selectedItem
request.transportType = .cycling
let directions = MKDirections(request: request)
do {
let response = try await directions.calculate()
returnedRoutes = response.routes
} catch {
print("Error calculating directions: \(error)")
}
关键点:
transportType = .cycling:今年新增的枚举值,之前只支持 walking/automobile/transit。MKMapItem.forCurrentLocation():source 用当前位置时不需要构造坐标。directions.calculate()仍是异步抛错的接口。- 返回的
response.routes可以直接配MapPolyline画在 SwiftUI Map 上。
反向地理编码用 MKReverseGeocodingRequest 替代 CLGeocoder(10:45):
// Reverse geocode with MapKit
import MapKit
let millCreekCoordinates = CLLocation(latitude: 39.042617, longitude: -94.587526)
if let request = MKReverseGeocodingRequest(location: millCreekCoordinates) {
do {
let mapItems = try await request.mapItems
millCreekMapItem = mapItems.first
} catch {
print("Error reverse geocoding location: \(error)")
}
}
关键点:
- 构造器返回 optional,
if let解包失败说明输入坐标不合法。 request.mapItems直接拿 MKMapItem 数组,省掉了 CLPlacemark 到 MKMapItem 的二次转换。- 第一个元素通常是最佳匹配,但仍要按业务判断置信度。
核心启发
-
把现有的 CRM/Excel 地址数据接入 PlaceDescriptor:很多 App 后端只有名称+地址,过去无法在地图上展示 Apple Maps 风格的标注。为什么值得做:上线后用户在 App 内就能看到官方营业时间、电话、Place Card。怎么开始:把
CLGeocoder.geocodeAddressString替换为PlaceDescriptor(representations: [.address(...)], commonName:)+MKMapItemRequest,一处改动覆盖整个数据导入流程。 -
给骑行类 App 接
transportType = .cycling:之前要么用步行路径凑合,要么自己接第三方骑行 API。为什么值得做:Apple Maps 的骑行数据覆盖了海拔、坡度、自行车道偏好,原生体验完整。怎么开始:在已有MKDirections.Request的代码里加一行request.transportType = .cycling,先验证路径质量再决定是否暴露给用户做模式切换。 -
在 App Intents 入参里使用 PlaceDescriptor:跨 App 传 CLLocation 会丢失店铺名、ID 等语义。为什么值得做:让 Shortcuts、Siri 把”附近的 X 店”这类参数稳定地传给你的 App。怎么开始:把现有 IntentParameter 的 location 字段替换成
PlaceDescriptor,并在supportingRepresentations里附带自家服务的 ID。 -
在 MapKit JS 中嵌入 Look Around 视图:网页端长期只能展示 2D 地图,街景需要跳到第三方。为什么值得做:旅游/房产网站直接在详情页显示 Apple 的 3D 街景,停留时长会上去。怎么开始:用
mapkit.PlaceLookup拿到 Place 后构造mapkit.LookAround(container, place, options),先用LookAroundPreview做缩略图占位,点击再展开完整视图。 -
统一改写老的
CLGeocoder调用为MKGeocodingRequest/MKReverseGeocodingRequest:旧 API 返回 CLPlacemark,需要再转 MKMapItem。为什么值得做:少一层转换,少一处出错点。怎么开始:搜代码库里CLGeocoder()的调用点,按地址→MKGeocodingRequest、坐标→MKReverseGeocodingRequest替换,注意构造器是 optional。
关联 Session
- Go further with MapKit — 同主题完整 session,覆盖 PlaceDescriptor、骑行路线、Look Around、统一地图 URL。
- Get to know App Intents — App Intents 框架基础,PlaceDescriptor 是它推荐的地点参数类型。
- What’s new in SwiftUI — SwiftUI Map 视图与 MapContentBuilder 的最新更新。
- Develop for Shortcuts and Spotlight with App Intents — 把 PlaceDescriptor 作为 Intent 参数暴露给 Shortcuts 与 Spotlight。
评论
GitHub Issues · utterances