View in English

  • 打开菜单 关闭菜单
  • Apple Developer
搜索
关闭搜索
  • Apple Developer
  • 新闻
  • 探索
  • 设计
  • 开发
  • 分发
  • 支持
  • 账户
在“”范围内搜索。

快捷链接

5 快捷链接

视频

打开菜单 关闭菜单
  • 专题
  • 相关主题
  • 所有视频
  • 关于

返回 WWDC25

  • 简介
  • 概要
  • 转写文稿
  • 代码
  • 深入了解写作工具

    借助写作工具,用户可以直接在你的 App 内进行文本校对、改写和转换。了解为你的 App 自定写作工具的高级技巧。探索众多格式选项,以及如何在富文本编辑中加以利用。如果你使用自定文本引擎,欢迎了解如何无缝整合完整的写作工具体验,以便用户直接在文本视图中进行修改。

    章节

    • 0:00 - 简介
    • 0:46 - 新功能
    • 2:21 - 自定原生文本视图
    • 4:00 - 富文本格式
    • 7:41 - 自定文本引擎
    • 16:58 - 后续步骤

    资源

    • Enhancing your custom text engine with Writing Tools
    • Writing Tools
      • 高清视频
      • 标清视频

    相关视频

    WWDC24

    • 开始使用 Writing Tools
  • 搜索此视频…

    大家好 欢迎观看讲座 “深入了解写作工具” 我是东原 主要负责文本输入和国际化相关工作 去年我们推出了写作工具 并展示了如何将它集成到 App 中 今天 我们将详细探讨进阶主题 我会介绍写作工具的全新功能、 如何在原生文本视图中 自定写作工具体验、

    如何让写作工具与富文本无缝协作

    以及如果 App 使用自定文本引擎 如何集成完整的写作工具体验 我们开始吧! 借助写作工具 用户可润色文字 直接在文本视图中 进行改写、校对或归纳总结 今年 我们为写作工具加入了 许多新功能 通过集成 ChatGPT 用户不仅可生成所需内容 还能根据简单提示轻松创作图像

    写作工具现已支持 visionOS 几乎适用于各类场景 包括邮件、 备忘录 甚至是你自己开发的 App

    iOS、iPadOS 和 macOS 26 新功能 是描述改写需求后 可输入后续请求

    例如让文本更温暖、 更口语化或更具鼓励性

    此外 写作工具还支持快捷指令 结合 Apple 智能 能够进一步提升工作效率 像校对、改写和归纳总结这样的功能 现也支持自动化处理

    我们还新增了多种 API 帮助 App 接入写作工具 你可使用系统默认的工具栏按钮 和标准菜单项 请求写作工具返回富文本的 Presentation Intent 或将功能强大的 WritingToolsCoordinator 集成到自定文本引擎中 稍后我会深入讲解新结果选项 和协调器 API

    接下来 我们来看看如何自定系统 提供的写作工具 原生文本视图

    去年的写作工具视频介绍了基础内容 对于原生文本视图 你可免费获得 写作工具的支持 你可利用它的生命周期方法 来响应写作工具的操作 比如暂停同步 你还可自定文本视图 选择使用 简化版或完整的写作工具行为 你可指定不想改写的文本范围 或通过结果选项控制是否支持 富文本、列表或表格 注意 在去年的讲座中 “结果选项”曾被称为 “允许的输入选项” 现在已更名为 “写作工具结果选项” 以清晰表明用途

    虽然写作工具可在选中文本时使用 但如果 App 中文本较多 建议像备忘录和邮件那样 添加工具栏按钮

    可在 UIKit 中使用 UIBarButtonItem 或在 AppKit 中使用 NSToolbarItem

    在上下文菜单中 写作工具项目会自动插入 如果你需要实现自定菜单 或希望重新安排这些项目的位置 可将 automaticallyInsertsWritingToolsItems 设为 false 再通过 WritingToolsItems API 获取标准菜单项 今年我们更新了菜单中的校对、 改写和归纳总结选项 使用 API 可免费获取这些更新

    现在来谈谈格式化

    App 中存在多种类型的文本视图 一些不支持富文本 例如访达中的搜索框 一些支持富文本 例如 TextEdit

    一些支持语义样式 例如备忘录 在这里 你可为段落指定标题、 副标题或块引用等语义样式 比如 写作工具在备忘录中 生成的内容 可使用原生节点、标题、表格和列表 要提示写作工具文本视图支持的 内容类型 可使用写作工具结果选项 对于纯文本视图 可使用 plainText 结果选项 写作工具仍会通过 NSAttributedString 与文本视图通信 但你可忽略其中的属性 对于富文本字段 如 TextEdit 可使用 richText 结果选项 并视你的视图字段是否支持列表 和表格 来决定是否启用这些选项 写作工具可能会向属性字符串中 添加显示属性 如加粗或斜体

    如果 App 对语义格式有特殊支持 如备忘录 可结合使用 richText 和 新presentationIntent 选项 写作工具会通过带有 Presentation Intent 的 NSAttributedString 与文本视图通信

    你可能想知道显示属性和 Presentation Intent 有何不同

    以 TextEdit 为例 写作工具通过使用加粗、 斜体等显示属性生成富文本 并将这些属性字符串传递给文本视图 这些属性只包含样式信息 如具体字号 但不包含语义样式信息 相比之下 备忘录会尽可能使用 原生的语义样式 如标题 虽然写作工具底层生成的文本相同 但我们会将 presentationIntent 添加到属性字符串中 备忘录随后可将它们转换为 内部的语义样式 从这个例子可看到 标题部分仅是一个并未包含 具体字体属性的标题意图

    请注意 即使在结果选项中启用了 Presentation Intent 写作工具仍可将属性添加到 属性字符串中 因为部分样式可通过 Presentation Intent 表达 本示例中 写作工具同时使用 强调型 Presentation Intent 和删除线显示属性 以表示截图中的文本 “关键但已删除”

    总之 在 Presentation Intent 模式 我们将尽可能 以 Presentation Intent 形式提供样式 这包括列表、表格和代码块等元素

    显示属性仍可用于下划线、 下标和上标等属性 最后 Presentation Intent 本身并不携带默认样式 你的 App 需负责将它们 转换为显示属性 或内部样式

    要让写作工具更好地理解文本语义 启用 Presentation Intent 后 可重写文本视图的 requestContexts 方法 并尽可能提供带 Presentation Intent 的上下文

    最后 即使你使用的是 完全自定的文本引擎 也没有问题

    你可免费获得基础写作工具体验 只要引擎采用了通用文本编辑协议 在 iOS 上 使用 UITextInteraction 或组合使用 UITextSelectionDisplayInteraction 与 UIEditMenuInteraction 在 macOS 上 视图需采纳 NSServicesMenuRequestor 协议 这样就能启用文本视图写作工具功能 并支持服务菜单中的相关特性 要进一步了解基础采用相关信息 请观看以下 WWDC24 讲座

    如果你想更进一步 也可集成完整的写作工具体验 这样 写作工具就能在 原地改写文本、添加动画 并直接内联显示校对修改 今年我们新增了适用于自定文本引擎 的 WritingToolsCoordinator API

    WritingToolsCoordinator 负责管理 视图与写作工具之间的交互

    你可将协调器附加到视图上 并创建代理以实现 WritingToolsCoordinatorDelegate 方法 代理负责提供写作工具 所需的上下文、 应用文本修改、并在动画过程中 提供预览对象、 提供写作工具绘制校对标记的坐标 以及响应状态变化 为了更直观地展示这一过程 我们来快速演示一个示例

    我这里有一个使用 TextKit 2 构建的自定文本引擎 如你所见 我们已实现了常用文本 编辑协议 如 NSTextInputClient 和 NSServicesMenuRequestor

    如果我构建并运行 App 即可免费 获得基础写作工具支持 所有结果会显示在面板中 比如我可执行改写操作

    然后选择替换或复制结果

    现在我们来实现完整的写作工具支持

    在 DocumentView 中 我会添加一些 写作工具会话所需的实例属性 并初始化一个 NSWritingToolsCoordinator 对象

    将 delegate 设为 self

    并将它绑定到 NSView 上 我还需要在“init”中调用这个 “configureWritingTools”

    当然 系统会提示 “DocumentView 尚不符合 NSWritingToolsCoordinator.Delegate 协议”

    我们可导入一个扩展文件 它可在 DocumentView 的扩展中 实现所有代理方法 你可看到 它包括准备上下文、

    执行文本替换与选择 返回校对标记的边界框、

    生成动画效果预览等

    下面我们来构建并运行 App

    如果改写文本

    可看到动画和文本变更会 直接在文本视图中生效

    如果进行校对 也会看到写作工具添加的下划线

    我还可点按每个建议 查看具体的修改内容

    接下来 我们将更详细地 讲解这些步骤

    首先要做的是创建一个协调器 并将它附加到视图上 UIKit 中的写作工具协调器 是 UIInteraction 与添加其他交互一样 可将它附加到 UIView 上 在 AppKit 中 它是 NSView 的一个实例属性 创建协调器后 你可设置所需的 写作工具行为和结果选项

    接下来 我们来看代理方法 最重要的一步是为 当前的文本提供上下文 上下文由 NSAttributedString 文本 和选择范围组成 属性字符串中至少需要包含 当前的文本选择 你也可加入 选择前后的段落 这样可帮助写作工具更好地理解 文本所处的上下文 根据 context.attributedString 中 当前的选择设置范围 如果未选中任何内容 则返回整篇 文档为上下文 并将范围设置为光标位置 这样 当用户没有明确选择文本时 写作工具仍有机会处理整篇文档 这就是提供上下文的方式 这里我展示的是 AppKit 但除非特别说明 你可以假定 UIWritingToolsCoordinator 和 NSWritingToolsCoordinator 的行为基本一致 代理方法是异步的 这是因为大型文本视图处理 底层文本存储可能需要较长时间 在函数的主体中 根据 scope 参数 准备文本和范围 大多数情况下 你只需返回 一个上下文 在复杂的文本视图中 可同时选取 多个文本存储内的内容 协调器也支持返回多个上下文

    分析完文本后 写作工具会将建议的修改 交给代理对象 在这个替换文本代理方法中 将修改应用到视图文本存储中 写作工具会针对每个独立的修改 调用这个方法 可能会对相同的上下文对象多次调用 这个方法并传入不同的范围值 完成处理后 写作工具可能会 请求代理更新选中的文本范围

    为了在写作工具处理期间 实现动画效果 协调器会请求指定文本范围的 预览图像

    TextView 应该会将文本渲染在 透明背景上 并返回预览图像 动画过程中 写作工具会对 这些预览图像应用视觉效果 而不是直接应用于实际文本 在 macOS 上 这一过程通过两个代理方法实现 第一个方法会接收一个数组 你至少需要为整个范围 返回一个预览图像 如果想让动画更流畅 也可为每一行返回一个预览

    在 iOS 上 UIKit 使用的是 UITargetedPreview 而非 NSTextPreview 且只需使用一个代理方法

    动画开始前和结束后 写作工具会 分别调用 prepareFor 和 finish 方法 在准备文本动画阶段 需要隐藏文本字段中特定范围的文本 动画结束后 再将它显示回来

    在校对过程中 写作工具会为 经过修改的 文本范围添加下划线 写作工具还会响应文本范围内的 点按事件 以显示内联校对弹窗

    为了显示校对标记 协调器会请求 代理 返回这些文本范围对应的贝塞尔路径 写作工具还需要边界贝塞尔路径 以响应点按或轻点事件

    最后 你可实现可选的 writingToolsCoordinator:willChangeToState:completion: 方法 以响应状态变化 你可能需要进行撤销合并、暂停同步 或禁止编辑 具体取决于你的文本视图实现 相反 当外部文本发生更改时 应使用 updateRange:withText 提醒协调器 以确保写作工具的操作 与当前文本保持一致 调用 updateForReflowText 方法 可提醒写作工具有关视图的布局变化 调用这个方法时 写作工具会请求 新的预览图像 校对标记以及其他与布局相关的信息

    至此 我们已经介绍了 如何将完整的写作工具体验 与强大的自定文本引擎进行集成 我们也发布了我之前演示过的 示例代码项目 欢迎查看示例代码以及 有关写作工具协调器的 完整文档进一步了解

    以上就是本次讲座的全部内容了 接下来要做什么呢? 体验新版写作工具功能 比如描述改写后的后续调整 或在 Apple Vision Pro 和 快捷指令 App 中使用写作工具

    如果你的 App 是以文本为主 可添加工具栏按钮

    尝试格式化选项 让写作工具能 读写语义样式 如标题、副标题、代码块

    如果你已经拥有强大的文本引擎 不妨进一步集成完整的写作工具功能

    要了解写作工具协调器的使用方式 请观看去年的讲座 “开始使用写作工具” 并查看下方链接中的示例代码 谢谢观看!

    • 11:46 - Attach a coordinator to the view (UIKit)

      // Attach a coordinator to the view
      // UIKit
      
      func configureWritingTools() {
          guard UIWritingToolsCoordinator.isWritingToolsAvailable else { return }
      
          let coordinator = UIWritingToolsCoordinator(delegate: self)
          addInteraction(coordinator)
      }
    • 12:02 - Attach a coordinator to the view (AppKit)

      // Attach a coordinator to the view
      // AppKit
      
      func configureWritingTools() {
          guard NSWritingToolsCoordinator.isWritingToolsAvailable else { return }
             
          let coordinator = NSWritingToolsCoordinator(delegate: self)
      
          coordinator.preferredBehavior = .complete
          coordinator.preferredResultOptions = [.richText, .list]
          writingToolsCoordinator = coordinator
      }
    • 13:06 - Prepare the context

      // Prepare the context
      
      func writingToolsCoordinator(_ writingToolsCoordinator: NSWritingToolsCoordinator,
              requestsContextsFor scope: NSWritingToolsCoordinator.ContextScope,
              completion: @escaping ([NSWritingToolsCoordinator.Context]) -> Void) {
      
          var contexts = [NSWritingToolsCoordinator.Context]()
                      
          switch scope {
          case .userSelection:
              let context = getContextObjectForSelection()
              contexts.append(context)
              break
              // other cases…
          }
              
          // Save references to the contexts for later delegate calls.
          storeContexts(contexts)
          completion(contexts)
      }
    • 13:48 - Respond to text changes from Writing Tools and update selected range

      // Respond to text changes from Writing Tools
      
      func writingToolsCoordinator(_ writingToolsCoordinator: NSWritingToolsCoordinator,
              replace range: NSRange,
              in context: NSWritingToolsCoordinator.Context,
              proposedText replacementText: NSAttributedString,
              reason: NSWritingToolsCoordinator.TextReplacementReason,
              animationParameters: NSWritingToolsCoordinator.AnimationParameters?,
              completion: @escaping (NSAttributedString?) -> Void) {
      }
      
      // Update selected range
      
      func writingToolsCoordinator(_ writingToolsCoordinator: NSWritingToolsCoordinator,
              select ranges: [NSValue],
              in context: NSWritingToolsCoordinator.Context,
              completion: @escaping () -> Void) {
      }
    • 14:41 - Generate preview for animation (AppKit)

      // Generate preview for animation (macOS)
      
      func writingToolsCoordinator(_ writingToolsCoordinator: NSWritingToolsCoordinator,
              requestsPreviewFor textAnimation: NSWritingToolsCoordinator.TextAnimation,
              of range: NSRange,
              in context: NSWritingToolsCoordinator.Context,
              completion: @escaping ([NSTextPreview]?) -> Void) {
      }
          
      func writingToolsCoordinator(_ writingToolsCoordinator: NSWritingToolsCoordinator,
              requestsPreviewFor rect: NSRect,
              in context: NSWritingToolsCoordinator.Context,
              completion: @escaping (NSTextPreview?) -> Void) {
      }
    • 14:58 - Generate preview for animation (UIKit)

      // Generate preview for animation (iOS)
      
      func writingToolsCoordinator(_ writingToolsCoordinator: UIWritingToolsCoordinator,
              requestsPreviewFor textAnimation: UIWritingToolsCoordinator.TextAnimation,
              of range: NSRange,
              in context: UIWritingToolsCoordinator.Context,
              completion: @escaping (UITargetedPreview?) -> Void) {
      }
    • 15:08 - Delegate callbacks before and after animation

      // Generate preview for animation
      
      func writingToolsCoordinator(
          _ writingToolsCoordinator: NSWritingToolsCoordinator,
          prepareFor textAnimation: NSWritingToolsCoordinator.TextAnimation,
          for range: NSRange,
          in context: NSWritingToolsCoordinator.Context,
          completion: @escaping () -> Void) {
      
          // Hide the specific range of text from the text view
      }
      
      func writingToolsCoordinator(
          _ writingToolsCoordinator: NSWritingToolsCoordinator,
          finish textAnimation: NSWritingToolsCoordinator.TextAnimation,
          for range: NSRange,
          in context: NSWritingToolsCoordinator.Context,
          completion: @escaping () -> Void) {
      
          // Show the specific range of text again
      }
    • 15:39 - Delegate callbacks to show proofreading marks

      // Create proofreading marks
      
      func writingToolsCoordinator(_ writingToolsCoordinator: NSWritingToolsCoordinator,
              requestsUnderlinePathsFor range: NSRange,
              in context: NSWritingToolsCoordinator.Context,
              completion: @escaping ([NSBezierPath]) -> Void) {
      }
      
      func writingToolsCoordinator(_ writingToolsCoordinator: NSWritingToolsCoordinator,
              requestsBoundingBezierPathsFor range: NSRange,
              in context: NSWritingToolsCoordinator.Context,
              completion: @escaping ([NSBezierPath]) -> Void) {
      }
    • 0:00 - 简介
    • 在本视频中,我们将介绍写作工具的新功能、如何自定 App 体验、支持富文本,以及如何将写作工具集成到自定文本引擎中。

    • 0:46 - 新功能
    • 写作工具现在支持与 ChatGPT、visionOS 相集成,可执行语气调整的后续请求,并可通过快捷指令实现自动化操作。写作工具还提供新的 API,可帮助你将其集成到你的 App 中。

    • 2:21 - 自定原生文本视图
    • 如果你的 App 使用原生文本视图,即可免费获得写作工具支持。你可以通过采用生命周期方法来响应暂停同步、在文本中指定忽略的范围、提供工具栏按钮或自定上下文菜单等操作,从而进一步自定使用体验。

    • 4:00 - 富文本格式
    • 写作工具现已支持包含语义样式的富文本。如果你的 App 支持多种 Presentation Intent,例如标题、副标题、引文、表格和列表,你可以将这些信息传达给写作工具。如果你的 App 支持特定的 Presentation Intent,写作工具将尽可能使用与之关联的样式来提供结果。

    • 7:41 - 自定文本引擎
    • 如果你的 App 使用自定文本引擎,现在也可以启用与写作工具的深度集成体验。只要你的引擎采用了通用的文本编辑协议,基础的写作工具功能即可自动生效。完整版写作工具体验支持写作工具直接原地改写文本、添加动画并以内联方式显示校对修改。要获得完整的体验,请使用新的 Writing Tools Coordinator API 将写作工具集成到你的自定文本引擎中。

    • 16:58 - 后续步骤
    • 你可探索写作工具的新功能,并在你的 App 中充分利用自定功能和富文本支持。如果你使用自定文本引擎,可采用 Coordinator API 来启用完整版写作工具体验。

Developer Footer

  • 视频
  • WWDC25
  • 深入了解写作工具
  • 打开菜单 关闭菜单
    • iOS
    • iPadOS
    • macOS
    • Apple tvOS
    • visionOS
    • watchOS
    打开菜单 关闭菜单
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    打开菜单 关闭菜单
    • 辅助功能
    • 配件
    • App 扩展
    • App Store
    • 音频与视频 (英文)
    • 增强现实
    • 设计
    • 分发
    • 教育
    • 字体 (英文)
    • 游戏
    • 健康与健身
    • App 内购买项目
    • 本地化
    • 地图与位置
    • 机器学习与 AI
    • 开源资源 (英文)
    • 安全性
    • Safari 浏览器与网页 (英文)
    打开菜单 关闭菜单
    • 完整文档 (英文)
    • 部分主题文档 (简体中文)
    • 教程
    • 下载 (英文)
    • 论坛 (英文)
    • 视频
    打开菜单 关闭菜单
    • 支持文档
    • 联系我们
    • 错误报告
    • 系统状态 (英文)
    打开菜单 关闭菜单
    • Apple 开发者
    • App Store Connect
    • 证书、标识符和描述文件 (英文)
    • 反馈助理
    打开菜单 关闭菜单
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program (英文)
    • News Partner Program (英文)
    • Video Partner Program (英文)
    • 安全赏金计划 (英文)
    • Security Research Device Program (英文)
    打开菜单 关闭菜单
    • 与 Apple 会面交流
    • Apple Developer Center
    • App Store 大奖 (英文)
    • Apple 设计大奖
    • Apple Developer Academies (英文)
    • WWDC
    获取 Apple Developer App。
    版权所有 © 2025 Apple Inc. 保留所有权利。
    使用条款 隐私政策 协议和准则