What's new in CarPlay
CarPlay 进阶 30m

CarPlay 新特性

What's new in CarPlay

2025年6月12日

在 Apple 官方观看视频

一句话判断

CarPlay 终于不再是导航和音乐播放器的独角戏了——WidgetKit 和 Live Activities 的引入,让任何有实时状态信息的应用都有机会出现在驾驶场景中,但谁先做出适配谁就能吃到红利。

这场 Session 讲了什么

CarPlay 以前给开发者的印象就是”能放个地图、能播个歌”。这次更新打破了这个边界。WidgetKit 正式登陆 CarPlay,意味着你现有的小组件不需要重写,只要加上 CarPlay 支持的 family 就能出现在车载屏幕上。Live Activities 也一样——外卖到哪了、航班延误了没有、打车还有几分钟到——这些信息现在可以直接在 CarPlay 界面上展示,用户不用再低头看手机。

另一条线是 CarPlay Ultra 的深度整合。通过 CPInstrumentClusterProviding 协议,导航应用可以把转弯方向、剩余距离这些结构化数据直接交给车辆仪表盘和 HUD 渲染。这对导航类应用的架构有直接影响:地图渲染和导航数据必须解耦,后者要能独立输出。

整体来看,Apple 在做的事情很明确:把 CarPlay 从”手机投屏”变成”原生车载信息平台”。对出行、物流、生活服务类应用来说,这是一个新的战场。

值得深挖的点

WidgetKit 的车载适配:不是简单加个 family 就完事

WidgetKit 登陆 CarPlay 的方式很聪明——复用现有的 Widget API,通过 supportedFamilies 加上 accessory 系列(.accessoryCircular.accessoryRectangular 等)就能让小组件出现在车载环境。但这里有个陷阱:车载场景和手机场景的设计逻辑完全不同。手机上你可以放一个中等尺寸的小组件,展示 5 天天气预报加上日出日落时间;但 CarPlay 上用户在开车,视线离开路面的时间不能超过 1-2 秒。这意味着 CarPlay 小组件只能放一个核心信息,字体要大,对比度要高,任何需要”仔细看”的设计都是在制造安全隐患。

另一个容易忽略的点是 CarPlay 的显示尺寸差异巨大——从 7 寸的小屏到 CarPlay Ultra 的全仪表盘覆盖,accessory 系列虽然在不同尺寸间有自适应能力,但开发者仍然需要针对不同分辨率做测试。Apple 建议用 CarPlay Simulator 做初筛,但真机验证不能省。还有一点:CarPlay 小组件不应该有任何可交互元素,这是硬性要求,不是建议。所有信息必须是静态的或自动更新的。

CPInstrumentClusterProviding:导航应用的架构分水岭

这个协议看起来只是一个新的 delegate 方法,但它暗示了一个架构层面的要求:导航应用必须把”地图怎么画”和”导航数据是什么”分开。以前你的导航数据可能直接耦合在 MKMapView 的渲染逻辑里,现在你需要一个独立的数据层,能输出 CPTravelEstimates——包含剩余距离和时间的结构化数据。

Trade-off 很明显:多一层抽象意味着更多的维护成本,但换来的是真正的多端适配能力。你的导航数据不仅能渲染到手机地图上,还能渲染到 CarPlay 的 map template、车辆仪表盘、甚至 HUD 上。对于大型导航应用来说,这个架构调整的工作量不小,但不做的话就等于放弃了 CarPlay Ultra 的仪表盘展示能力——而这个能力对用户来说感知度极高,因为它直接出现在驾驶时最常看的位置。

代码片段

示例 1:为小组件添加 CarPlay 支持

给现有小组件加上 CarPlay 的 accessory family 支持。

struct MyWidget: Widget {
    var body: some WidgetConfiguration {
        StaticConfiguration(kind: "com.example.weather", provider: WeatherProvider()) { entry in
            WeatherWidgetView(entry: entry)
        }
        .supportedFamilies([.systemSmall, .systemMedium, .accessoryCircular, .accessoryRectangular])
    }
}

坑:accessory 系列的布局空间极小,别指望在 .accessoryCircular 里塞超过一个数字和一个图标。

示例 2:展示 Live Activity

外卖应用在 CarPlay 上展示配送状态。

let attributes = DeliveryAttributes(orderNumber: "ORD-12345")
let state = DeliveryAttributes.ContentState(
    deliveryStatus: "骑手已取餐",
    estimatedArrival: Date().addingTimeInterval(900)
)
let activity = try Activity<DeliveryAttributes>.request(
    attributes: attributes,
    content: .init(state: state, staleDate: Date().addingTimeInterval(1800))
)

坑:staleDate 设太短会导致 CarPlay 上显示过期信息,设太长又可能误导驾驶员,建议按实际配送时长的 1.2 倍来设。

示例 3:为仪表盘提供导航数据

把导航元数据同步到车辆仪表盘。

class NavigationSession: NSObject, CPInstrumentClusterProviding {
    func instrumentClusterControllerDidConnect(_ controller: CPInstrumentClusterController) {
        controller.associatedMapTemplate = self.mapTemplate
    }

    func updateEstimates() {
        let estimates = CPTravelEstimates(
            distanceRemaining: Measurement(value: 500, unit: .meters),
            timeRemaining: 120
        )
        mapTemplate.updateEstimates(estimates, for: currentManeuver)
    }
}

坑:CPTravelEstimates 的数据必须和实际导航状态同步,延迟超过 3 秒就会让驾驶员困惑。

最佳实践

建议先从 Live Activities 入手,而不是 WidgetKit。原因很简单:Live Activities 的 CarPlay 展示不需要额外的 UI 设计工作——iPhone 上已经做了锁屏和灵动岛的展示,CarPlay 只是多一个展示位。先把已有的 Live Activity 在 CarPlay 上跑起来,验证数据流是否通畅,再考虑 WidgetKit 的适配。

第二步才是 WidgetKit。优先用 accessory family 做一个最简版本——只展示一个核心数字或状态词。别急着做复杂的布局,CarPlay 上的信息密度比想象的低得多。

最后才是 CPInstrumentClusterProviding。这个需要架构层面的改动,工作量大,而且只对导航类应用有意义。如果不做导航,可以先跳过。但如果是导航应用,这个改动应该排在最前面,因为 CarPlay Ultra 的仪表盘展示是差异化最大的能力。

还有什么值得关注

CarPlay 所有应用都获得了新的模板选项,布局灵活性比以前好不少。隐私问题变得突出——车载场景下可能有乘客在旁边,敏感信息(比如订单金额、联系人姓名)需要谨慎处理。CarPlay Simulator 是开发阶段的主要测试工具,但焦点导航的体验差异只有真机才能暴露。

CarPlay WidgetKit LiveActivities