Explore enhancements to App Intents
Swift & UI 进阶 20m

探索 App Intents 的增强功能

Explore enhancements to App Intents

2023年6月5日

在 Apple 官方观看视频

一句话判断

App Intents 今年全面接管 Widget 配置(替代 SiriKit Intent Definition File)、实现 Widget 交互(按钮和开关触发代码)、新增 IntentParameterDependency 实现参数联动,还扩展了 Shortcuts 集成和静态提取能力。

这场 Session 讲了什么

Shortcuts 团队的 Roman Efimov 介绍了 App Intents 在 iOS 17 中的全面增强,涵盖三个方向:Widget 集成、开发者体验改进和 Shortcuts 集成更新。

Widget 配置用 App Intents:过去配置 Widget 需要 Xcode 中的 Intent Definition File。现在可以直接在 Widget Extension 代码中定义 WidgetConfigurationIntent,使用 AppIntentConfiguration 替代 IntentConfiguration。Xcode 提供一键迁移按钮,将 SiriKit Intent 自动转换为 App Intent 代码。

Widget 交互:SwiftUI 的 Button 和 Toggle 现在支持 App Intents。在 Widget 视图中将 App Intent 关联到按钮,用户点击就能直接执行应用代码(如设置闹钟、切换设置),不需要打开应用。

IntentParameterDependency:新增的属性包装器,允许在 DynamicOptionsProvider 或 Query 中访问其他参数的值。比如根据用户选择的公交站点过滤可用路线。这个 API 在 Widget、Shortcuts 和 Focus Filters 中通用。

开发者体验改进:框架支持扩展(更多框架的实体和枚举可用作参数)、静态提取增强(编译时发现更多 App Intent 信息)。

Shortcuts 集成:App Intent 代码可以同时服务于 Widget 配置、Widget 交互和 Shortcuts 动作——一个 Intent 定义,三种用途。

值得深挖的点

AppIntentConfiguration 的统一力量:一个 WidgetConfigurationIntent 既是 Widget 的配置描述,也是 Shortcuts 中的可发现动作。SetAlarm Intent 既是 Widget 中按钮触发的动作,也是 Shortcuts 中可搜索的操作。这种复用大幅减少了代码量。

IntentParameterDependency 的级联过滤:这是参数联动的核心机制。用户选择站点后,路线选项自动过滤为该站点的可用路线。实现方式是在 Query 中用 @IntentParameterDependency 引用 Intent 的参数,然后在 results() 方法中读取这些参数来动态过滤。

SiriKit 到 App Intents 的一键迁移:Xcode 可以自动将 Intent Definition File 转换为 App Intent 代码。迁移后需要确保参数名和类型完全匹配,否则已有 Widget 会在更新后失效。用户更新应用时 Widget 会自动迁移,但只有一次机会。

静态提取的增强:编译器现在能从更多代码位置提取 App Intent 的元数据(标题、描述、参数),让 Siri 和 Shortcuts 能更好地发现和理解你的 App Intent。

代码片段

// Widget 配置 - 使用 AppIntentConfiguration
struct NextBusWidget: Widget {
    var body: some WidgetConfiguration {
        AppIntentConfiguration(
            kind: "NextBus",
            intent: NextBusConfigurationIntent.self,
            provider: NextBusProvider()
        ) { entry in
            NextBusWidgetEntryView(entry: entry)
        }
    }
}

// 配置 Intent - 直接在代码中定义
struct NextBusConfigurationIntent: WidgetConfigurationIntent {
    static var title: LocalizedStringResource = "Next Bus"
    static var description = IntentDescription("Show next bus arrival")

    @Parameter(title: "Bus Stop")
    var busStop: BusStopEntity

    @Parameter(title: "Route")
    var route: RouteEntity

    @Parameter(title: "Direction")
    var direction: Direction
}
// Widget 交互 - 按钮触发 App Intent
struct SetAlarmIntent: AppIntent {
    static var title: LocalizedStringResource = "Set Alarm"
    @Parameter(title: "Departure Time")
    var departureTime: Date

    func perform() async throws -> some IntentResult {
        // 在应用中设置闹钟
        AlarmManager.setAlarm(at: departureTime)
        return .result()
    }
}

// Widget 视图中使用
Button(intent: SetAlarmIntent(departureTime: entry.nextBusTime)) {
    Text(entry.nextBusTime.formatted())
}
// IntentParameterDependency - 参数联动
struct RouteQuery: EntityQuery {
    @IntentParameterDependency(\.busStop)
    var busStop: BusStopEntity?

    func results() async throws -> [RouteEntity] {
        guard let stop = busStop else { return [] }
        // 根据选择的站点过滤路线
        return RouteManager.routes(for: stop)
    }
}
// 动态选项提供者
struct BusStopOptionsProvider: DynamicOptionsProvider {
    func results() async throws -> [BusStopEntity] {
        // 提供所有可用的公交站点
        return BusStopManager.allStops.map { stop in
            BusStopEntity(id: stop.id, name: stop.name)
        }
    }
}

最佳实践

  • 新项目直接用 AppIntentConfiguration:不再需要 Intent Definition File,所有配置在代码中完成。
  • 一个 Intent 多种用途:Widget 配置、Widget 交互和 Shortcuts 动作可以共享同一个 App Intent 实现。
  • 迁移时保持 Schema 一致:从 SiriKit 迁移时,参数名和类型必须完全匹配。添加新参数时用可选或带默认值的方式。
  • 利用 IntentParameterDependency 做级联选择:当参数之间有依赖关系时(如站点->路线),用这个 API 提供上下文感知的选项。
  • 测试迁移只做一次:用户更新应用后 Widget 自动迁移,只有一次机会。发布前要充分测试。

还有什么值得关注

  • App Intents 正在成为 Apple 平台集成的统一入口——Widget、Siri、Shortcuts、Focus Filters 都通过它工作。
  • 静态提取的增强意味着你不需要做额外注册工作,编译器自动发现你的 Intent。
  • Session 推荐配合 “Dive into App Intents” 和 “Bring your widget to life” 一起看。
  • 动态选项和查询(DynamicOptionsProvider / EntityQuery)是 App Intents 体系中最强大的部分,值得深入学习。
WWDC 2023