Highlight
CarPlay 的设计哲学一直是「为驾驶者服务」。你的 app 在 CarPlay 上应该只提供驾驶时真正需要的功能,登录、配置、阅读条款这些事留给 iPhone。
核心内容
CarPlay app 的难点是克制。车上的用户正在驾驶,界面必须少、任务必须短、信息必须一眼看完。
(00:55)Apple 在开场给了一个很明确的边界:CarPlay 是为驾驶者设计的。一次性配置、登录、阅读条款,都应该放在驾驶前或驾驶后完成,不应该出现在 CarPlay UI 里。
这条边界决定了后面的所有设计。
(01:59)iOS 16 新增两类 CarPlay app:Fueling 和 Driving Task。前者把 iOS 14 的 EV Charging 思路扩展到加油和替代燃料场景;后者给极简单的驾驶任务一个正式入口。
(09:16)Apple 还发布了 CarPlay Simulator。它是 Mac 上的独立应用,连接 iPhone 后可以在桌面复现真实 CarPlay 环境。开发者可以同时使用 Xcode、Instruments,并测试不同屏幕尺寸、外观、断连重连和仪表盘显示。
(14:53)导航 app 还有一个新能力:在支持的车辆上,把实时地图或转向卡片显示到数字仪表盘(instrument cluster)。如果 app 已经支持 CarPlay Dashboard,这个改造沿用同一套模式:在 Info.plist 里声明 scene,随后实现对应 delegate。
详细内容
CarPlay 模板替你控制复杂度
(02:14)CarPlay 的 UI 由模板(template)组成。app 提供数据,系统负责把 UI 绘制到车载屏幕上。
这件事有三个直接收益。
第一,开发者不需要自己处理字体大小和车载输入设备差异。第二,模板会把 UI 复杂度压低。第三,同一类模板在不同 CarPlay app 中保持一致,驾驶者能更快完成操作。
本 session 没有给出模板 API 的官方代码片段,但明确列出了几个模板的使用场景:
// 概念示例:根据 session 中提到的模板选择 UI 形态
let roadStatusTemplate = CPPointOfInterestTemplate(...)
let accessoryTemplate = CPInformationTemplate(...)
let quickChoiceTemplate = CPGridTemplate(...)
关键点:
CPPointOfInterestTemplate:session 用它举例道路状态 app,适合展示用户附近的少量重要地点。CPInformationTemplate:session 用它举例拖车控制器,适合展示一个配件状态和少量操作按钮。CPGridTemplate:session 用它举例里程记录和快速车道收费,适合一两个快速选择按钮。
这里的重点是模板限制。不同 app 类型只能使用相关且适合驾驶场景的模板,Apple 在开发者文档中提供了对应表格。
Fueling app 要做加油过程,不只是找地点
(04:26)iOS 16 新增 Fueling app 类型。它来自 iOS 14 的 EV Charging app 思路,但对象扩展到传统燃油车和替代燃料车辆。
Apple 特别提醒:很多用户已经会用导航 app 查找并驶向某个地点。所以 Fueling app 在 CarPlay 上只做“找加油站”并不够。
更合适的功能是驾驶时真正需要的加油流程,例如连接到正确的加油站设备,或直接启动加油泵。
// 概念示例:Fueling app 的 CarPlay UI 应该围绕驾驶时动作
struct FuelingAction {
let stationName: String
let pumpIdentifier: String
let primaryActionTitle = "Start Pump"
}
关键点:
stationName:CarPlay UI 只需要展示当前相关的地点,不应该做完整地点规划。pumpIdentifier:session 明确提到 app 可以帮助用户连接到正确设备。primaryActionTitle:核心动作应该是启动加油泵这类驾驶中需要完成的任务。
这个示例是概念模型,不是 Apple 提供的新 API。官方 transcript 只说明产品边界和场景,没有给出 Fueling 类型的代码片段。
Driving Task app 应该短到几秒完成
(05:22)Driving Task 是新的 CarPlay app 类型,用来承载更广泛的简单驾驶任务。
Apple 给了四类例子:道路状态信息、车辆配件控制、行程开始或结束时的任务、快速车道收费人数选择。这些任务的共同点是小,最好单屏完成。
(08:40)设计规则很硬:考虑做成单屏 app,只提供驾驶时最小必要功能,只允许几秒内完成的任务,避免复杂或低频用例。
// 概念示例:Driving Task 的操作集合应该很小
let mileageActions = [
CPGridButton(titleVariants: ["Personal"], image: personalImage) { _ in
recordPersonalMileage()
},
CPGridButton(titleVariants: ["Business"], image: businessImage) { _ in
recordBusinessMileage()
}
]
关键点:
mileageActions:session 中的里程记录 app 只有两个按钮,分别记录个人或商务里程。CPGridButton:session 说明这类 app 可以使用CPGridTemplate,按钮式选择适合几秒内完成。recordPersonalMileage()/recordBusinessMileage():示例函数只表示业务动作,session 没有提供具体实现。
这个例子保留了 transcript 中的 UI 形态,但函数名是概念性的。不能把它当作官方完整 API 示例。
CarPlay Simulator 让真机调试回到桌面
(10:18)CarPlay Simulator 是一个独立 Mac 应用。下载 Additional Tools for Xcode,运行应用,用线缆把 iPhone 连到 Mac,CarPlay 就会像连上真实汽车一样启动。
它解决的是测试成本。
以前要在真实 iPhone 上测试 CarPlay UI,通常需要真实车辆或 aftermarket head unit。现在可以坐在桌前调试真机 app,同时用 Xcode 断点和 Instruments 做性能分析。
(12:38)Simulator 还提供多种车辆行为开关:限制 UI、切换深浅色外观、模拟断开和重连、调整主显示屏尺寸、启用仪表盘第二屏。
CarPlay Simulator 测试清单:
1. 切换 light / dark appearance,检查图像资源。
2. 点击 Limit UI,确认行驶中内容会被适当缩短。
3. 改变 main display size,检查模板和地图绘制。
4. 启用 instrument cluster display,检查第二屏地图或转向卡片。
5. 模拟 disconnect / reconnect,调试重连逻辑。
关键点:
- 第 1 步:session 演示了 Express Lane app 为深浅色提供不同 artwork。
- 第 2 步:Limit UI 按钮用于模拟车辆行驶时要求 CarPlay 限制屏幕内容。
- 第 3 步:模板 UI 通常由系统适配,导航 app 的地图绘制代码需要重点验证。
- 第 4 步:仪表盘第二屏主要面向导航 app。
- 第 5 步:手机仍连接 Mac,断连重连场景可以直接用 Xcode 调试。
导航 app 接入数字仪表盘
(15:07)数字仪表盘支持沿用 iOS 13 CarPlay Dashboard 的模式。先在 Info.plist 声明支持,再添加对应 Scene Session Role。
官方代码片段如下:
<key>UIApplicationSceneManifest</key>
<dict>
<!-- Indicate support for CarPlay dashboard -->
<key>CPSupportsDashboardNavigationScene</key>
<true/>
<!-- Indicate support for instrument cluster displays -->
<key>CPSupportsInstrumentClusterNavigationScene</key>
<true/>
<!-- Indicate support for multiple scenes -->
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UISceneConfigurations</key>
<dict>
<!-- For device scenes -->
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneConfigurationName</key>
<string>Phone</string>
<key>UISceneDelegateClassName</key>
<string>MyAppWindowSceneDelegate</string>
</dict>
</array>
<!-- For the main CarPlay scene -->
<key>CPTemplateApplicationSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>CPTemplateApplicationScene</string>
<key>UISceneConfigurationName</key>
<string>CarPlay</string>
<key>UISceneDelegateClassName</key>
<string>MyAppCarPlaySceneDelegate</string>
</dict>
</array>
<!-- For the CarPlay Dashboard scene -->
<key>CPTemplateApplicationDashboardSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>CPTemplateApplicationDashboardScene</string>
<key>UISceneConfigurationName</key>
<string>CarPlay-Dashboard</string>
<key>UISceneDelegateClassName</key>
<string>MyAppCarPlayDashboardSceneDelegate</string>
</dict>
</array>
<!-- For the CarPlay instrument cluster scene -->
<key>CPTemplateApplicationInstrumentClusterSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>CPTemplateApplicationInstrumentClusterScene</string>
<key>UISceneConfigurationName</key>
<string>CarPlay-Instrument-Cluster</string>
<key>UISceneDelegateClassName</key>
<string>MyAppCarPlayInstrumentClusterSceneDelegate</string>
</dict>
</array>
</dict>
</dict>
关键点:
CPSupportsDashboardNavigationScene:声明 app 支持 CarPlay Dashboard 导航 scene。CPSupportsInstrumentClusterNavigationScene:声明 app 支持数字仪表盘导航 scene。UIApplicationSupportsMultipleScenes:允许 app 同时管理多个 scene。CPTemplateApplicationSceneSessionRoleApplication:主 CarPlay scene,用于车机主屏。CPTemplateApplicationDashboardSceneSessionRoleApplication:Dashboard scene,用于 CarPlay Dashboard。CPTemplateApplicationInstrumentClusterSceneSessionRoleApplication:数字仪表盘 scene,用于仪表盘地图或转向卡片。UISceneDelegateClassName:为每个 scene 绑定对应 delegate,分别处理 phone、CarPlay、Dashboard 和 instrument cluster。
(16:00)声明 scene 之后,还要实现仪表盘相关 delegate。官方片段如下:
extension TemplateApplicationSceneDelegate: CPTemplateApplicationInstrumentClusterSceneDelegate {
func templateApplicationInstrumentClusterScene(
_ templateApplicationInstrumentClusterScene: CPTemplateApplicationInstrumentClusterScene,
didConnect instrumentClusterController: CPInstrumentClusterController) {
// Connected to Instrument Cluster
TemplateManager.shared.clusterController(instrumentClusterController, didConnectWith: templateApplicationInstrumentClusterScene.contentStyle)
}
…
func instrumentClusterControllerDidConnect(_ instrumentClusterWindow: UIWindow) {
// Window in which to draw instrument cluster contents
self.instrumentClusterWindow = instrumentClusterWindow
}
关键点:
CPTemplateApplicationInstrumentClusterSceneDelegate:让 scene delegate 接收仪表盘 scene 的连接事件。didConnect instrumentClusterController:当 CarPlay 连接到仪表盘控制器时调用。CPInstrumentClusterController:用于处理仪表盘相关控制,例如 session 后面提到的缩放、罗盘、限速显示时机。templateApplicationInstrumentClusterScene.contentStyle:把当前内容样式传给 app 自己的模板管理逻辑。instrumentClusterControllerDidConnect(_:):系统把可绘制的UIWindow交给 app。self.instrumentClusterWindow:app 保存这个窗口,随后在其中绘制仪表盘内容。
(16:26)仪表盘还有几个额外注意点。车辆可能允许用户缩放地图,这需要通过 CPInstrumentClusterControllerDelegate 实现。罗盘或限速显示也要等 delegate 告诉 app 何时适合绘制。
(16:57)仪表盘画面可能被车内其他元素遮挡。处理方式是安全区域(safe area):在 view controller 里重写 viewSafeAreaInsetsDidChange,并用 cluster view 的 safeAreaLayoutGuide 约束关键内容。
// 概念示例:把关键地图内容限制在安全区域内
final class ClusterMapViewController: UIViewController {
override func viewSafeAreaInsetsDidChange() {
super.viewSafeAreaInsetsDidChange()
updateRouteOverlayLayout(using: view.safeAreaLayoutGuide)
}
}
关键点:
viewSafeAreaInsetsDidChange():session 明确提到可重写它来获知安全区域变化。view.safeAreaLayoutGuide:session 建议用它保证关键内容位于可见区域。updateRouteOverlayLayout:概念函数,代表 app 自己更新路线线条、当前位置等关键地图内容。
核心启发
1. 做一个只保留驾驶动作的配件控制 CarPlay UI
- 做什么:把拖车、车顶箱、胎压设备这类配件控制压缩成一个
CPInformationTemplate页面。 - 为什么值得做:session 的拖车控制器例子说明,CarPlay UI 可以只包含状态和少量按钮,配对、配置等复杂功能留在 iPhone。
- 怎么开始:先列出驾驶中必须操作的 1-2 个动作,再用 CarPlay 模板表达;不要把 iPhone 设置页迁移过去。
2. 做一个两按钮的里程记录入口
- 做什么:在驾驶开始或结束时,让用户用两个按钮记录 personal / business mileage。
- 为什么值得做:Apple 用这个例子说明 Driving Task app 的理想形态:单屏、短任务、几秒完成。
- 怎么开始:用
CPGridTemplate组织少量按钮,按钮回调只写入当前行程分类,详细统计放回 iPhone app。
3. 给导航 app 增加仪表盘地图验证流程
- 做什么:在 CarPlay Simulator 中启用 instrument cluster display,检查地图、转向卡片和安全区域。
- 为什么值得做:iOS 16 允许导航 app 把地图或 turn card 放到驾驶者视线内的数字仪表盘。
- 怎么开始:在 Info.plist 添加
CPSupportsInstrumentClusterNavigationScene和 instrument cluster scene role,再实现CPTemplateApplicationInstrumentClusterSceneDelegate。
4. 建立 CarPlay Simulator 回归测试清单
- 做什么:每次发布前测试深浅色、Limit UI、屏幕尺寸、断连重连和仪表盘第二屏。
- 为什么值得做:这些都是 session 中 CarPlay Simulator 明确支持的车辆环境模拟能力。
- 怎么开始:把 Additional Tools for Xcode 加入团队开发环境,真机连接 Mac 后逐项验证,导航 app 重点测试不同 display size 和 aspect ratio。
关联 Session
- What’s new in MapKit — 了解 MapKit 的 3D 地图、覆盖物和 Look Around 更新,适合导航 app 继续优化地图体验。
- Meet Apple Maps Server APIs — 学习地理编码和 ETA 等服务端地图能力,为路线和地点服务补齐后端能力。
- Bring multiple windows to your SwiftUI app — 理解 scene 与窗口结构,有助于把多 scene 思路迁移到 CarPlay 配置中。
- Explore navigation design for iOS — 从信息结构和交互简化角度,对照 CarPlay 的驾驶场景约束。
评论
GitHub Issues · utterances