Highlight
MapKit 团队的 Eric 和 Yingxiu 系统介绍了 iOS 16 中 MapKit 的五项重大更新。自从 Apple Maps 推出全新地图和沉浸式 Look Around 体验以来,覆盖范围已经扩展到加拿大、多个欧洲国家和日本,去年还引入了包含车道标线、人行横道、自行车道的 3D 城市体验。今年 MapKit 把这些能力全部开放给了第三方开发者。
核心内容
地图 App 的难点不在“放一张地图”。难点在地图和业务内容如何共存。
租车、导航、旅行、商店定位这类 App,通常会在地图上叠加运营区域、路线、兴趣点和详情卡片。以前这些内容很容易盖住地图标签,或者在 3D 城市里被建筑遮挡。用户看到的是一层业务图形,地图本身的道路、建筑和地形反而退到后面。
(02:13)iOS 16 的 MapKit 先降低了升级成本:用新 SDK 重新编译后,iOS、macOS、tvOS App 会自动使用新的 Apple map,并在可用地区显示 3D City Experience。然后,MapKit 增加了配置、覆盖物、混合模式、可选择地图要素和 Look Around 五组 API,让业务内容可以贴着真实地图工作。
这场演讲的示例 App 是一个旧金山 scooter 租赁 App。它有四个功能:运营区域、骑行路线、探索 waterfront 兴趣点、查看景点 Look Around。后面的每个 API,都落在这个具体场景里。
详细内容
用 Map Configuration API 原子化配置地图
(02:41)iOS 15 以前,开发者通过 MKMapView 上的多个属性配置地图。iOS 16 软废弃这些分散属性,引入 MKMapConfiguration 作为新的中心入口。
MKMapConfiguration 是抽象基类,下面有三个具体配置:
MKImageryMapConfiguration:只显示卫星影像。MKHybridMapConfiguration:显示影像地图,并叠加道路标签和兴趣点等地图要素。MKStandardMapConfiguration:显示完全图形化的标准地图。
这些配置还能控制地形。elevationStyle 可以是 flat 或 realistic。标准地图还支持 emphasisStyle,其中 muted 会降低地图细节对比度,把注意力让给你自己的图形内容。
// 概念示例:根据 transcript 中出现的配置类和属性整理,省略真实项目中的兼容性判断。
let configuration = MKStandardMapConfiguration()
configuration.elevationStyle = .realistic
configuration.emphasisStyle = .muted
configuration.showsTraffic = true
mapView.preferredConfiguration = configuration
关键点:
MKStandardMapConfiguration()选择图形化标准地图,对应演讲中“fully graphics-based map”。elevationStyle = .realistic请求真实地形,地图会显示山丘、道路高差和 3D 城市效果。emphasisStyle = .muted降低地图细节对比,让叠加的业务图形更突出。showsTraffic = true对应标准地图和混合地图都支持的交通显示开关。preferredConfiguration把这些选择作为一个配置对象交给MKMapView,避免多个属性分散修改。
(05:42)3D City Experience 有硬件和区域限制。iOS 需要 A12 或更新设备,macOS 需要 M1 或更新 Mac。不可用地区会回退到平面地图;其他设备也会显示平面版本。演讲建议同时测试 3D 和 flat fallback。
覆盖物不再粗暴压住地图
(06:55)MapKit 的 overlay 一直有两个层级:aboveRoads 和 aboveLabels。aboveLabels 会盖在所有内容上,包括标签。Apple 建议只在不希望数据和地图交互时使用它。
iOS 16 把 aboveRoads 作为新的默认层级。它会让覆盖物位于地形、道路、土地覆盖和水体之上,同时保留标签的上下文。
// 概念示例:演讲的 Operating Area 功能把 polygon 作为运营区域叠加到地图上。
let operatingArea = MKPolygon(coordinates: coordinates, count: coordinates.count)
mapView.addOverlay(operatingArea, level: .aboveRoads)
关键点:
MKPolygon对应演讲中“polygon overlay”,用来表示 scooter 的可运营区域。addOverlay把业务区域加入地图。level: .aboveRoads选择 iOS 16 推荐层级,覆盖物不会盖住地图标签。- 如果选择
aboveLabels,覆盖物会盖住更多地图上下文,只适合少数场景。
(08:11)iOS 16 还增加了 transparent buildings。地图有 pitch 时,树和建筑如果挡住 aboveRoads 覆盖物,会自动变透明;pitch 回到 0 度时,冲突的地面对象会从视图中消失,让覆盖物完整可见。
演示里,Yingxiu 把运营区域的 alpha 改成 0.8。这样即使不倾斜地图,用户也能看到下面的道路和建筑。
// 概念示例:renderer 中把 polygon 填充改成半透明。
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolygonRenderer(overlay: overlay)
renderer.fillColor = UIColor.systemPurple.withAlphaComponent(0.8)
return renderer
}
关键点:
rendererFor overlay是 MapKit 用来绘制 overlay 的委托入口。MKPolygonRenderer负责绘制 polygon。withAlphaComponent(0.8)对应演讲中把 alpha 改成0.8的操作。- 半透明 overlay 和 transparent buildings 会组合生效,地图仍然保留空间上下文。
路线 overlay 可以跟随真实地形
(13:14)普通 overlay 加到 realistic terrain 地图上时,MapKit 会自动把地图切换到 flat。删除最后一个 overlay 后,再恢复 realistic。例外是 Directions API 返回的路线 overlay,它会跟随真实地形。
演示里的 Ride 功能从 Presidio Park entry 到 Battery Spencer,请求一条穿过 Golden Gate Bridge 的路线。路线线条会沿着桥和道路的高差显示,甚至能从桥墩、树木前方透出来。
// 概念示例:演讲用 Directions API 获取路线,并把 route polyline 加到地图。
let source = MKMapItem(placemark: MKPlacemark(coordinate: startCoordinate))
let destination = MKMapItem(placemark: MKPlacemark(coordinate: endCoordinate))
let request = MKDirections.Request()
request.source = source
request.destination = destination
let directions = MKDirections(request: request)
let response = try await directions.calculate()
if let route = response.routes.first {
mapView.addOverlay(route.polyline, level: .aboveRoads)
}
关键点:
MKPlacemark把起点和终点坐标包装成地点。MKDirections.Request保存 source 和 destination。MKDirections请求路线。route.polyline是 Directions API 返回的路线 overlay。- 这类 overlay 是演讲中特别说明的例外:它能保留 realistic terrain,而不是把地图压回 flat。
(16:28)elevated route line 支持 A12 及更新 iOS 设备。旧设备会自动得到 2D 地图上的 2D 路线。
用 blendMode 控制 overlay 和地图的视觉关系
(17:02)如果目标只是让自定义内容更突出,不一定要把 overlay 放到 aboveLabels。iOS 16 给 MKOverlayRenderer 增加了 blendMode 属性,可以使用 CoreGraphics 的 blend mode。
演讲用 Presidio National Park 做例子:先用一个带 cutout 的大 overlay 覆盖地图区域,再分别设置 hue、hard light、color burn 等混合模式。结果是公园外区域被去饱和并变暗,公园内部仍保持关注度。
// 概念示例:演讲明确说明 MKOverlayRenderer 新增 blendMode 属性。
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolygonRenderer(overlay: overlay)
renderer.fillColor = UIColor.gray
renderer.blendMode = .colorBurn
return renderer
}
关键点:
MKOverlayRenderer是所有 overlay renderer 的基类。blendMode是 iOS 16 新增属性。.colorBurn来自 CoreGraphics blend mode,演讲用它得到更克制的 Presidio 高亮效果。- overlay 的插入顺序会影响结果:底部 overlay 先和地图混合,上层 overlay 再和前一次结果混合。
让用户直接选择地图上的 POI、区域和自然要素
(20:09)过去,用户只能点你自己放到地图上的 annotations。地图里 Apple 提供的商店、餐厅、地标、城市、州、山脉、湖泊等要素只是背景。
iOS 16 的 Selectable Map Features API 改变了这一点。开发者可以配置哪些 map features 可选,然后通过 delegate 接收选择事件。
// 概念示例:演讲的 Explore 功能只启用 points of interest。
mapView.pointOfInterestFilter = MKPointOfInterestFilter(excluding: [
.airport,
.carRental,
.hospital,
.laundry
])
mapView.selectableMapFeatures = [.pointsOfInterest]
关键点:
pointOfInterestFilter对应演讲中先排除无关 POI 类别的步骤。.airport、.carRental、.hospital、.laundry是演示中点名排除的类别。selectableMapFeatures是新的可选地图要素配置入口。- 示例只选择
.pointsOfInterest,演讲还提到 territories 和 physical features 也可选。
(22:41)用户点击地图要素后,MapKit 会走两个入口。新的 didSelect annotation 回调用来处理选择事件;已有的 viewFor annotation 回调用来定制选中状态的 annotation view。
// 概念示例:演讲通过 MapFeatureAnnotation 定制选中样式,并发起 MKMapItemRequest。
func mapView(_ mapView: MKMapView, didSelect annotation: MKAnnotation) {
guard let feature = annotation as? MKMapFeatureAnnotation else { return }
Task {
let request = MKMapItemRequest(mapFeatureAnnotation: feature)
let mapItem = try await request.mapItem
showInfoCard(for: mapItem)
}
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard let feature = annotation as? MKMapFeatureAnnotation else { return nil }
let view = MKMarkerAnnotationView(annotation: feature, reuseIdentifier: "Feature")
view.markerTintColor = .systemPurple
view.glyphImage = feature.iconStyle.image
view.selectedGlyphImage = feature.iconStyle.image
return view
}
关键点:
MKMapFeatureAnnotation是 iOS 16 新类型,表示用户选中的地图要素。feature.iconStyle提供 POI 的图标和颜色信息,演讲用它保留 Apple iconography。MKMapItemRequest根据 map feature 请求更完整的MKMapItem。MKMapItem可提供地址、名称、电话号码和 URL。viewFor annotation返回nil时,MapKit 使用默认渐变 annotation;返回自定义 view 时,可以套用 App 自己的品牌颜色。
把 Look Around 放进自己的界面
(31:14)Look Around 从 iOS 13 开始存在于 Maps app。iOS 16 把它带进 MapKit。开发者可以在自己的 App 中先显示一个小预览,用户点击后进入全屏可交互视图。
使用流程有三步:检查目标位置是否有 Look Around 数据;把 scene 传给 Look Around view controller 或 snapshotter;如果数据可用,就更新 UI 显示预览。
// 概念示例:演讲说明 LookAroundSceneRequest 可用 coordinate 或 map item 初始化。
let request = MKLookAroundSceneRequest(mapItem: mapItem)
let scene = try await request.scene
if let scene {
lookAroundViewController.scene = scene
previewContainer.isHidden = false
} else {
previewContainer.isHidden = true
}
关键点:
MKLookAroundSceneRequest是 iOS 16 新类,用来检查某个位置是否有 Look Around 数据。scene是 optional async property。可用时返回 scene,不可用时返回nil,请求出错时抛出错误。- Look Around scene 是 opaque object,只作为可用性和显示所需的 token。
lookAroundViewController.scene = scene对应演讲中把 scene 赋给已有 view controller 的做法。previewContainer.isHidden表示 UI 应根据数据是否可用来显示或隐藏预览。
(36:44)Yingxiu 的 Highlights 功能把 MKLookAroundViewController 嵌入底部左侧容器。用户选择 Ferry Building 时,地图先用新 camera API 动画到地点;动画完成后,请求 Look Around scene;有数据就显示预览。Ferry Building 是 landmark,会得到 curated camera framing;Dragon Gate 不是 landmark,所以得到 top-down view。
如果只需要静态图,也可以使用 MKLookAroundSnapshotter 获取 snapshot。
// 概念示例:演讲提到 snapshotter 适合只需要静态图片的场景。
let request = MKLookAroundSceneRequest(coordinate: coordinate)
if let scene = try await request.scene {
let snapshotter = MKLookAroundSnapshotter(scene: scene)
let snapshot = try await snapshotter.snapshot
imageView.image = snapshot.image
}
关键点:
MKLookAroundSceneRequest(coordinate:)使用坐标检查可用性。MKLookAroundSnapshotter接收 scene。snapshot是 async property,返回静态预览图。- 这种方式适合列表卡片、搜索结果或轻量预览,不需要一开始就嵌入完整交互控制器。
核心启发
1. 做一个城市骑行运营区地图
- 做什么:在地图上显示可骑行区域、禁停区和推荐停车点。
- 为什么值得做:
aboveRoads、transparent buildings 和半透明 polygon 能让运营区域不遮挡道路、标签和建筑。 - 怎么开始:用
MKPolygon表示区域,插入到.aboveRoads,再用MKPolygonRenderer设置半透明填充。
2. 做一条带真实高差的城市步行路线
- 做什么:为桥梁、坡道、公园路线显示贴合地形的路线线。
- 为什么值得做:Directions API 返回的 route polyline 是普通 overlay 的例外,可以保留 realistic terrain。
- 怎么开始:用
MKDirections.Request请求路线,把route.polyline加到地图,并在 A12 及更新设备上测试 3D 效果。
3. 做一个可点击的景点探索地图
- 做什么:用户点击地图上的餐厅、地标、博物馆后,弹出品牌化信息卡。
- 为什么值得做:Selectable Map Features 让 Apple 地图内置 POI 变成可交互对象,不必自己维护全部 annotation 数据。
- 怎么开始:配置
selectableMapFeatures = [.pointsOfInterest],在didSelect中用MKMapItemRequest获取地址、URL 和电话。
4. 做一张带视觉重点的公园或商圈地图
- 做什么:高亮目标区域,压暗或去饱和周边地图。
- 为什么值得做:
MKOverlayRenderer.blendMode可以控制 overlay 和地图底图的混合方式,比把图层盖在标签上更自然。 - 怎么开始:准备目标区域 polygon 和外部遮罩 polygon,按顺序插入 overlay,并试验
.hue、.hardLight、.colorBurn等 blend mode。
5. 做一个景点 Look Around 预览卡
- 做什么:用户选中地标后,在地图角落显示 Look Around 小窗口,点击进入全屏街景。
- 为什么值得做:
MKLookAroundSceneRequest可以先判断数据是否存在,避免空白 UI。 - 怎么开始:用 map item 创建 request,拿到 scene 后赋给
MKLookAroundViewController;没有 scene 时隐藏预览容器。
关联 Session
- Meet Apple Maps Server APIs — 客户端 MapKit 和服务端 Apple Maps Server APIs 共同组成完整地图能力栈。
- Meet WeatherKit — WeatherKit 提供和位置强相关的天气数据,适合叠加到地图和出行场景。
- Get more mileage out of your app with CarPlay — CarPlay 导航类 App 需要结合 MapKit 的地图、路线和驾驶场景 UI。
评论
GitHub Issues · utterances