WWDC Quick Look 💓 By SwiftGGTeam
Develop for Shortcuts and Spotlight with App Intents

Develop for Shortcuts and Spotlight with App Intents

观看原视频

Highlight

三个板块:Use Model action、Spotlight on Mac、Automations on Mac。

核心内容

写 Shortcut 最烦的事情,是格式不对就接不上。模型给一段话,下一步要 Boolean,于是又得加一个解析步骤。从一段 PDF 提取金额、日期,要写正则。把 ChatGPT 输出的富文本贴进 Bear 这种笔记应用,加粗和表格全丢。这些「胶水步骤」占据了快捷指令大半篇幅,也是用户放弃的常见原因。

WWDC25 的解法是新的 Use Model action01:20)。这个 action 让用户在 Shortcut 中调用 Apple Intelligence 模型,可选 Private Cloud Compute 服务器模型、设备端模型,或 ChatGPT。真正决定开发者体验的,是它和后续 action 的衔接方式:当下一个 action 需要 Boolean,runtime 自动把模型输出转成 yes/no;需要结构化字段,模型输出 Dictionary;需要应用实体,模型从传入的 entity 列表里筛选并返回 App Entity。开发者不需要改代码,但需要让 entity 暴露足够的信息——因为模型看到的是 entity 的 JSON 表示。

除了模型 action,session 还讲了两件 Mac 专属的事:Spotlight 现在可以直接运行 App Intent10:43),不再只是搜索;个人自动化登陆 Mac17:18),新增文件夹、外置硬盘等触发类型。这两件事的共同前提是:你的 App Intent 必须设计得够规整,参数摘要完整、entity 暴露 find action、富文本参数用 AttributedString。

详细内容

模型如何看见 App Entity06:51)。当用户把 entity 列表传给模型,系统会把每个 entity 序列化成 JSON 喂给模型。JSON 包含三部分:

  1. 所有暴露给 Shortcuts 的 entity 属性,全部转为字符串。
  2. Type Display Representation 的 name,告诉模型这是哪类东西(如 “Calendar Event”)。
  3. Display Representation 的 title 和 subtitle。

entity 在 Shortcuts 里展示什么,模型就看到什么。如果你只暴露了 idtitle,模型无法基于「开始时间」筛选事件。

Find action 的两种实现方式08:06)。要让模型拿到 entity,得先有 Find action。两条路径:

  • 手写 query:实现 EnumerableEntityQueryEntityPropertyQuery
  • 走 Spotlight 索引:让 entity 实现 IndexedEntity,然后用新 API 把 entity 属性关联到 Spotlight attribute key,系统自动生成 Find action。

第二条路径在本届有新 API:indexingKeycustomIndexingKey09:05)。前者把属性映射到系统已有的 Spotlight 属性键(比如事件标题对应 eventTitle),后者用于没有现成键的属性(比如自定义 notes)。

struct EventEntity: IndexedEntity {
    @Property(indexingKey: \.title)
    var eventTitle: String

    @Property(customIndexingKey: "notes")
    var notes: String

    static var typeDisplayRepresentation = TypeDisplayRepresentation(name: "Event")

    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(title: "\(eventTitle)", subtitle: "\(notes)")
    }
}

关键点:

  • IndexedEntity 协议让 entity 同时进入 Core Spotlight 索引和 Shortcuts Find action。
  • indexingKey: \.titleeventTitle 关联到 Spotlight 已有的标题属性键,系统据此生成「按标题搜索」的 Find action。
  • customIndexingKey: "notes" 用字符串自定义键,适合没有内置 Spotlight 属性键的字段。
  • typeDisplayRepresentation 的 name(“Event”)会写进喂给模型的 JSON,作为类型提示。
  • displayRepresentation 的 title 和 subtitle 也会进 JSON——模型能读到的细节,正是这里展示的字段。

让 Intent 出现在 Spotlight 里的两个硬要求12:34):

  1. 参数摘要(parameter summary)必须包含所有「无默认值的 required 参数」。少一个,intent 就在 Spotlight 中消失。
  2. Intent 不能被隐藏:isDiscoverable = falseassistantOnly = true、或仅用作 widget 配置(无 perform 方法)的 intent,都不会出现。

如果新加了一个 required 的 notes 参数但没写进摘要,intent 就消失。修复有三种:把它写进摘要、改成 optional、或给个默认值(如空字符串)。

前后台分离运行16:20)。Spotlight 用户有时只想「快进快出」(在后台创建事件),有时想看到结果(跳进 app 看新建的事件)。Apple 推荐拆成两个 intent:背景 intent(如 CreateEventIntent)执行后通过 Opens Intent 关联前景 intent(如 OpenEventIntent)。这样同一个动作既能背景跑,也能在需要时把 app 拉到前台。

Follow Up09:50)。Use Model action 有个 Follow Up toggle:开启后,用户在初始结果出来之后还能输入下一句来调整输出(demo 中是「double the recipe」)。对开发者的影响:你的 intent 接收的输入可能比一次性请求更丰富、更不规整。

Automations on Mac17:18)。新增文件夹(folder)和外置硬盘(external drive)两种 Mac 专属触发器,加上沿用 iOS 的 Time of Day、Bluetooth 等。规则简单:只要 intent 在 macOS 可用,就能挂到 Mac 自动化上——包括能装到 Mac 上的 iOS app。

核心启发

  • 从「模型能读懂什么」反推 entity 设计:每个 @Property 暴露的属性、displayRepresentation 的 title/subtitle、typeDisplayRepresentation 的 name,都会序列化进 JSON 喂给模型。为什么值得做:模型基于 JSON 推理,没有暴露的字段约等于不存在。怎么开始:拿一个核心 entity,把它当前的 JSON 表示打印出来,问自己「光看这段 JSON,能不能筛选/排序」,缺什么补什么。

  • 富文本参数全部改用 AttributedString:模型经常输出加粗、列表、表格。为什么值得做:用 String 接收会让模型生成的格式静默丢失,用户体验突然变差。怎么开始:搜代码里所有 intent 的文本参数,凡是 app 内部本来就支持富文本的(笔记、邮件、文档),把类型从 String 换成 AttributedString,配合 What’s New in Foundation 里的新 API。

  • 审计参数摘要,让 intent 上 Spotlight:Spotlight on Mac 是免费的入口,但 intent 不规整就上不去。为什么值得做:Mac 用户每天敲 Cmd+Space 几十次,能在那里直接跑你的 action 是巨大流量。怎么开始:列出所有 intent,逐个检查参数摘要是否覆盖了所有无默认值的 required 参数;缺的,要么写进摘要,要么改 optional,要么补默认值。

  • 拆背景/前景双 intent,用 Opens Intent 串联:单一 intent 要么总开 app(烦人),要么永远不开(看不到结果)。怎么开始:选一个「创建型」action(创建事件、添加任务、记一笔账),新建一个 OpenXxxIntent,让原 intent 的 perform 返回 OpensIntent 关联到它,由用户的入口决定走哪条路径。

  • 给所有参数补 Suggestions:在 Spotlight 里点开参数字段却没有任何建议,是劝退现场。怎么开始:大列表(事件、邮件、文档)实现 EntityQuerysuggestedEntities,比如「未来一天的日历事件」;有限集合(时区、币种、语言)实现 EnumerableEntityQueryallEntities;动态搜索补 EntityStringQuery,或直接走 IndexedEntity 让系统接管。

关联 Session

评论

GitHub Issues · utterances