大多数浏览器和
Developer App 均支持流媒体播放。
-
认识 macOS 快捷指令
macOS 中加入了快捷指令,您的 app 是该过程的关键部分。了解如何通过将功能设置为快捷指令操作,以提升 app 性能。我们将向您展示如何为采用 Catalyst 或 AppKit 的 macOS app 构建操作,跨平台部署操作、发布和共享快捷指令,以及让您的 app 实现从其他 app 运行快捷指令。我们还将向您介绍快捷指令如何与 Automator 和 AppleScript 等现有 Mac 自动化技术相适应。
资源
相关视频
Tech Talks
WWDC21
-
下载
大家好 我叫绚香 很高兴能在此为您介绍 Mac的Shortcuts
我想先给您一个 Mac Shortcuts的快速概览 同时还有一些Shortcuts方面 今年新引入的精彩更新 Shortcuts使人们可以 将重复性工作自动化 联动不同App的功能 以解决问题 它令您可以创造性地使用您的技术 Mac的Shortcuts将会使操作自动化 更有趣 更易触达
当您第一次打开该App 会看到所有快捷键 已经与iPhone同步了 其中包括了一个Shortcuts总库 这里存有各种您可以直接使用的快捷键 还包括一些全新的Mac专属快捷键 若您想创建自己的快捷键 可以使用快捷键编辑器 该板块是重新设计的 让您的Mac体验更加舒适 另外 几乎整个Mac版app 都是在SwiftUI里编写 这就让我们可以确保 iOS和Mac 版本的代码基础的统一 同时还能将其调整修改的 更适合其对应的平台
例如在iOS中 任何Mac的App 都可以向Shortcuts提供动作 本课程中 我们将讲解 如何通过App对Shortcuts的支持 在macOS下构建强大的工作流程 无论您开发的是iOS的app 一个Mac的app 还是用Mac Catalyst构建的App
我们还会讲解Shortcuts如何 与Mac的自动化结合使用 介绍一些已有可用的工具 例如备受喜爱的 AppleScript和Automator
今年我们还为 Focus和Sound Recognition 新添了2个自动化类型 还有一整套全新的操作 使您可以更好的管理窗口和文件 还有更多精彩 稍后为您一一呈现
本课程还会讲解您的App要如何为用户 提供自定义的动作来创建强大的快捷键
另外 若您的App 集成了file provider功能 那么新的“文件”操作会 自动处理您的App提供的文件 若您的App会采用 已有的SiriKit的消息意图 现在我们通过一个自定义的 从App“发送消息”操作 来实现这个功能
还有一些共享方面的令人兴奋的新特性 我们深知开发者 很喜欢构建和共享快捷键 今年我们还使快捷键的分发 比之前简便 我们提供了一种新的文件格式 您可将快捷键以文件形式分发 此次我们实现了私有共享 使您可以方便地与亲友共享快捷键 我们来看一下吧
每个人都可以直接下载Shortcuts 无需做出任何特殊的设置修改 这就意味着您可以将自己的快捷键 发布到自己的网页或App中
例如 假设一组快捷键 采用的是来自你的App的动作 您想要拿给别人 现在您创建好了快捷键 然后从iCloud分享出去 Apple对其进行公证 然后转化成一条链接 您可以在自己的App或网页上引用 非常便于其他人下载使用
当别人下载快捷键时 会向您的App传递数据 例如他们的库中的照片等 为此我们通过提供更多特定的许可提示 以保证人们可以更好的控制自己的数据 还有更多精彩之处 现在我们还以文件的方式共享快捷键 特别是当您需要在iCloud之外 分发快捷键时 和iCloud链接一样 快捷键文件也要经由Apple认证 以确保其安全性
最后同样重要的是 今年引入一种新的快捷键私密共享方式 您无需将其上传到iCloud 便可分享给联系人或作为个人备份
快捷键文件内 都有发送方的身份签名 若您需要对一组快捷键重新签名 则可以使用Shortcuts命令行工具 这些就是Shortcuts今年新引入的 精彩特点 现在一起看一下Shortcuts 与现存的Mac自动化技术 如何一起发挥作用吧 Mac对于一直对自动化都大力支持 例如AppleScript Shell Scripting和Automator 这里我们很兴奋地告诉大家 Shortcuts对于AppleScripts 和Shell Scripting的支持都非常好 我们引入了新动作 且内建到Shortcuts中 您可以在Shortcuts的编辑器中 直接编写和运行脚本
接下来我们看一下Automator Automator是Mac上已存的自动化工具 您可通过它为重复性的工作 创建自动化的工作流程 Shortcuts是Mac自动化的未来之星 但我们对Automator 和该应用忠实用户 也十分重视 为了使从Automator到 Shortcuts的过渡尽量流畅丝滑 我们构建了一款搬家工具 它可将大部分Automator工作流程 转换成Shortcuts流程 例如 您有一个工作流程 它可以仅选中Finder中 PDF格式的图片 Shortcuts可以将其导入 并将每个Automator动作 转换成一个或多个Shortcuts动作
您只需在Shortcuts里 打开工作流程文件就行 可以直接拖拽到应用里 也可以通过右键菜单实现 就这样就行了 您的工作流程就已经转化成快捷键了 为了支持这个搬家工具 我们向Shortcuts添加了大量 常用的Automator 操作运行 Shell Scripts和AppleScripts的操作 管理文件的操作等等 所以这些操作 都能被搬家工具支持 现在我们看看您的App 要如何结合Shortcuts使用 了解一下它能为顾客创造的价值 App与Shortcuts结合的最主要方式 是将它的一些功能 开放给“操作”来执行 将操作开放给Shortcuts后 用户可以更快捷地使用App的功能 创建更强大的工作流程 最后同样重要地 可以联合您的App 和其他App一起使用 我们一起深入了解一下这些内容 在macOS中有很多地方 用户可以使用快捷键 当您的App开放某个操作 人们就可以或在Shortcuts里 或通过Shortcuts菜单栏来使用 可以通过键盘操作 也可以通过Spotlight搜索 方法很多的
这样用户就能更快捷地 使用您App的某功能 且应用场景也会大幅扩展 除此之前 您App的操作 还可成为强大的多步骤快捷键的一部分 假设您开发了一款待办清单App 帮助用户管理自己的任务 若您的App的功能可通过操作来使用 眨眼之间 用户就可以通过这些操作 创建强大的工作流程 例如 我可以创建一个快捷键 查到所有明天到期的待办事件 将优先级设定到成“高” 用列表形式展示给我 而所有这些可一键完成 当您将一些操作开放后 通过不同的组合方式 将操作串联起来 您会开启数千种App功能的新用法 当您的App将一些操作开放后 用户还可以将其功能 与其他的App一起联动
例如假设您开发了一款图片编辑App 然后开放一个操作 来应用App的自定义图片滤镜 嗖一下子 我们就可以用这个操作 构建这样一个工作流程 让我可以选用一张照片 然后应用滤镜 接着发布到社交媒体上 一键实现上述所有工作 这仅仅是通过开放操作 拓展用户使用您APP的场景的例子 请务必观看关于操作设计的课程 看看自己可以创建哪些绝妙的操作 帮助用户更好使用您的App 接下来我们把镜头交给伊恩 他会展示如何创建操作 大家好 我是伊恩 今天我将为您展示 如何为Mac的App 创建Shortcuts 操作 稍后我还会讲解一些 集成过程中要牢记的特殊要求 那么接下来我们一起来创建操作吧 和iOS一样 Shortcuts的操作也是 使用意图框架(Intents framework) 构建的 又被称为SiriKit 本课程中我会假装 我在开发一款协作性任务管理App 它会帮助用户记录待办事件 登记每件事的到期日 并于其他人共享这些待办事件 所以确保用户无论在哪里都可以 在Mac上使用我App的功能是很重要的 通过结合Shortcuts 我的用户就能创建多步骤快捷键 来处理App中的各种任务
来看一下这个App 用户交互的主要内容 是一个任务(Task) 每个任务拥有一系列重要的属性 第一条属性是标题(title) 它是一条描述代办事件内容的文本 任务还有对应的到期日 和将任务共享给别人的链接 对这些App中的任务 您有多个可执行的操作 这里我们可以看作是动词 您可以添加新任务 也可编辑或删除现存任务 让任务匹配某个特定标准 当然还有让App为您显示某个特定任务 针对每个动词 我要创建对应的操作 这些会形成用户可以请求调用的 最基本操作 有了这些操作 用户就可以联合起来实现一些目的
例如您可以选中一条任务 然后删除它 这通过联合两个操作可以实现
通过Create Task 用户可以创建一条自动化工作流程 根据Notes上选定的文本 在必要的时候对其进行首字母大写 然后要求用户输入到期日 接着Shortcuts就可以 将文本和到期日 传递给Create Task 操作 该操作会传递这条意图 在我的App里创建任务 当该任务已经在App中完成创建 这条意图会将返回这件任务 其中包括了共享用的URL 快捷键可将这条链接通过消息发给别人
这仅仅是一个实例 因为Shortcuts中有那么多不同的操作 利用Create Task 操作的场景 几乎是毫无限制的 现在我知道了App能开放哪些操作 接着就可以着手实现它们
实现的第一步 就是为App创建一个意图定义文件 将该文件添加到Xcode项目 它就会跟着您的源代码一起编译
本课程中 我们的例子是 一个Mac的非常基础的SwiftUI的App 然而 无论您使用什么UI框架 添加意图的过程基本都一样 首先我会创建一个意图定义文件
在模板界面上 搜索意图定义(intent definition)
默认的名称就可以 确保将其添加到App目标 这样它才会编译
这就是一个新建的 空白的意图定义文件
在文件中 我需要 定义App实现的每个意图 以及其他需要用到的类型 本例中就是任务 这款App有很多意图 一一对应任务类型 所以我们从定义任务类型开始入手 点击左下角的“+”按钮 然后选择新类型“New Type”
每个类型自动带有 识别符和displayString属性
displayString属性对应任务的名称 但是我们还需给类型添加一些属性 对应到期日和共享链接 首先我添加一条到期日属性 用以说明该任务必须在何时之前完成
我要给日期选择类型 因为该属性代表的是日期和时间
我还要添加一个URL作为该任务的链接 可用来分享给其他人
第一个任务这就完成了 接着我要定义一个意图 该意图用来创建一个任务
这里我将其命名为“Create Task” 将编目更改为“Create”
我还会编写一条简短的描述 用以概括此意图
用户浏览App可用的操作列表时 就会看到该描述 接着我要定义意图的参数 意图可以被看做一个函数 而参数就相当于实参 它们会被传送给函数来进行作业
为了创建一个新任务 我的App需要知道任务名称和到期日 所以要为其各设定一个参数 共享链接则不需要在这里就填写收集 因为当任务创建之后 App自己会生成链接 现在我们开始为名称添加参数
类型选择字符串
每个类型的参数 都携带有一些相关配置选项 如果需要 您可以设定一个默认值 而本例中 我直接设定成空字符串即可 接下来添加到期日的参数 类型选择Date Components
这里我再添加一个弹窗提示 当用户没有输入日期时 实时跳出来要求用户填写
两个参数都定义好之后 基本都完工了 最后 我需要往下拉页面 找到Shortcuts的App的区域 再填写一些东西 首先我要设定一个输入参数 由于用户一般是从别的地方获取文本 然后传递入我们的操作 所以我将名称参数作为输入项 这可以提升用户创建快捷键的体验 若在快捷键中 用户已从之前的操作获取了文本内容 它会在添加操作的时候 进行自动填写 最后一步 定义一个总结 当用户在快捷键中查看该操作时 会显示这条字符串 这里概述写为 “创建任务并填写到期日”
要创建一个任务 两个参数都是必填的 所以概述里我也写上这二者 当您查看该操作时 就一定能看到它们 若您还有更多参数 但是您并不想都塞到概述里 那也完全可以 这样一来 用户就可以扩展这个操作并进行编辑
当您完成了意图的定义 Xcode会生成类和协议 供您在实现中使用 现在我要开始创建App 这将确保我们的意图定义没有问题 然后我们在继续往下 在构建代码段中 可以看到生成了一些新代码 这些源文件是由Xcode 基于意图定义里的内容生成的 Xcode为任务的类型生成源代码 以及CreateTaskIntent
这些新的类现在就可以 在App的代码集里使用了 另外 现在意图已经被定义好 我就可以启动Shortcuts 然后创建新的快捷键 这时候就能搜索到 新添加的Create Task动作了 当然现在它不能真的工作 因为我还未编写代码 接下来 App需要分发和处理 到来的意图 当用户通过Shortcuts 或Siri运行该操作时 这段代码就会被运行
Apps需要决定 用哪个进程处理它们的意图 这里有两个选项 第一种 in-app处理 或第二种 构建一个独立的意图扩展
In-app意图处理 允许App来控制自己的状态 以应答流入的意图 决定哪些传送给App委托 大部分App应该先用这种方法 必要时再考虑意图扩展
意图扩展是一种轻量的 可独立运行的进程 它可以代表App处理意图 由于每次要运行一个意图时 就要启动一个进程 那么创建意图扩展 就有助于尽可能提高效率 因为App自己并不用启动
Apps和意图扩展会被要求实例化 并为每个流入的意图 返回一个意图句柄对象 我们看一下为此 需要实现的API有哪些
当进行in-app意图处理时 有若干AppDelegate方法可用 它们允许你返回意图句柄
在macOS Monterey中 NSApplicationDelegate也支持该API 对于意图扩展 INExtension的子类可以覆盖 handlerForIntent方法
关于更多不同in-app处理 和意图扩展的详情 请观看WWDC 2020的 “赋能您的意图”课程
现在我将到App中 进行in-app意图处理的实现 首先我要将CreateTaskIntent 作为App支持的意图 添加进来 这可以让系统知道 该意图应该被传送给App的委托
接着前往App的主源代码
首先我要为App创建一个委托 由于这里使用的 是SwiftUI的App生命循环 所以这里还要创建一个委托适配器 将对象连接到SwiftUI
要接收意图 就要导入意图框架 并实施handlerForIntent方法
这就是分发方法的内容 下一步是为意图生成句柄
在本例中 我要创建一个新的类 来处理意图 这可以是您App中的任何对象 意图句柄必须 与为该意图生成的协议相一致 最后结尾的单词都是“Handling” 对于“Create Task”的意图 其名字为CreateTaskIntentHandling
然后我更新handlerForIntent方法 当意图是CreateTaskIntent时 返回一个新的IntentHandler对象
Xcode会告诉你 需要使用什么方法来实现
意图处理协议 可以包含4类方法 解析 提供选项 确认和处理 每个参数都会生成 一个对应的解析方法 这是一次检测的机会 您可以检查参数是否有效 若无效 则告诉系统要怎么处理
本意图有两个解析方法 一个针对名称 另一个针对到期日
对于名称这个参数 App必须确保证不是nil且非空
若名称是空值 则返回needsValue 它会告诉系统提示用户输入一个值
对于到期日参数 也要进行同样的检测 核实该到期日是有效的 且不是nil 查看一下App对于到期日的要求 解析方法同样需要确保 所有的到期日都是在将来 若该日期已经过去了就要向用户报错
为此 我要回到意图定义文件中 添加一条自定义针对有效性的报错
这里的代码栏填入invalidDate 并给出报错消息 提示用户到期日必须是在将来时间里
现在App遇到不支持的结果时 就能返回我刚才添加的 针对有效性的报错 显示一条报错消息 提示该日期无效 另一种方法就是提供选项 任何动态选项设置为可用的参数 都有这个选项 若您的参数 只有有限的可用值 您不想用户自己随意输入值 那您可以为该参数启用动态选项
这会创建一个名为提供选项的方法 允许您在意图运行时 直接规定有什么可能的值 Shortcuts会要求用户 从中直接选取一个 待所有参数都各自解析完成 您可以有选择地使用确认方法 您可在这一步确保一切都正常 检查是否应该能够处理意图 且当遇到问题 也能提供报错 举个例子 假如我们需要网络连接 您就应该在这一步进行检测 以确保当前设备确实连接到网络了
最后 处理方法这里 则是您具体执行意图提出的要求的环节
处理方法会在App里创建任务 然后返回成功结果 在操作创建了任务之后 它应该将任务作为输出结果提供出去 这样 后一步的动作就能使用其属性 例如共享URL 回到意图编辑器里 找到意图的应答选项区域 我要在这里 为创建好的任务添加一条属性
在这里选中我之前创建的任务 还要将该属性设置为意图的输出结果 这样Shortcuts就可以用它了 现在回到代码里 应答就拥有了一个任务属性 我可以在这里分配任务对象
这一切做好之后 您的意图现在就应该 作为操作出现在Shortcuts里了 请确保花些时间对它进行测试 尝试各种用户可能会利用它的方式 要开始测试 我将再次打开Shortcuts 查看“Create Task”动作
我要为任务填写名称和日期 “明天下午3点”
当我点击“运行”按钮 这条任务就成功创建好了 但是若我将日期改成“昨天下午3点”
就会如我们预料的一样弹出报错消息 这就是在Shortcuts中 构建动作的过程 最后 今天我要还讲解一些 在Mac中针对Shortcuts做开发时 需要您牢记的注意点
这里我要讲四种不同的App 包括用Mac Catalyst构建的App 处理文件的App 有iOS和Mac双版本的App 以及其他需要运行Shortcuts的 各种App和工具
首先 若您使用Mac Catalyst 进行iOS App到Mac的转移 您需要记住以下几点 在macOS Monterey中 通过Mac Catalyst建立的App 可以使用相同的意图API 若您构建一个新的App 那么所有的东西都应该 和iOS上的一模一样
然而若您的App已存的是Mac版本 您集成了来自iOS的意图框架 那很可能在转移到Mac的过程中 您的意图集成被关闭了 所以 请审核您的代码 确保在macOS Monterey运行时 重新启用了这项功能
另一个我要强调的App类型 是基于文档的App 之前的实例中 我们的任务管理App 处理的是完全存在于App中的任务 然而有很多其他的App是针对 硬盘上已存的文档文件进行操作的 在iOS 15和macOS Monterey中 针对意图的文件参数 允许用户选中特定的文件 并传递给您App的动作进行操作 若您的App主要处理基于文件 而非自数据库的文档 那请考虑构建一套 专门对文件进行操作的动作 例如 一个电子制表App 可以创建一个动作 去打开一个文档 或对特定文件的某一行添加一组数据
本节课程中还有另一个 第三方快捷键操作文件的绝妙例子 那就是与 Sound Analysis结合使用
当您开发了一款 iOS和Mac双版本的App 若想让您的动作在两个平台上都能使用 您就要在两个版本中 都部署相同的意图 这样用户就能在一个平台上构建快捷键 然后在另一个平台上同样可用 要做到这一点 您应该在两个版本的App中 都编译完全一样的意图定义 确保两边的意图的名字和参数都一样
有时候您的App在不同平台 拥有bundle识别符可能不一样 这个没关系 Shortcuts会为您代为处理 但请牢记一点 拥有相同名称的意图只能在 来自同一Apple Developer团队 部署的App间共享
还有 在iOS 15上 若您需要对用户从一个App版本 升级到另一个 只要两个App来自同一个开发者 且使用相同的意图名称 您的App快捷键就会自动地 从一个版本转到另一个 最后 若您想要从App 或者命令行运行快捷键 有2种方法可以考虑 第一种 Shortcuts有一个脚本界面 这里允许Mac的apps和AppleScripts 列表并运行Shortcuts 另外 还有一个快捷键命令行工具 它允许你在Shell Scripts里 或命令行工具里 列表并运行Shortcuts
若您的App或脚本 可以通过运行Shortcuts 获得更好的利用 那请使用脚本界面 (Scripting interface) 通过与“快捷键事件 (Shortcuts Events)”通讯 您的App可以获得一个 用户设置的快捷键列表 还可以对其进行运行
在AppleScrip您可通过 告诉(tell)“快捷键事件” 运行指定名称的快捷键来实现
当使用Scripting Bridge框架 您可以直接从Swift 或Objective-C的App中 请求快捷键事件去运行某个快捷键 对于沙盒App 您需要添加一条entitlement 称作“com.apple.security. scripting-targets”
为了获取快捷键列表并运行它们 您还需要添加 “com.apple.shortcuts.run”目标 最后 macOS Monterey 还有一项命令行工具 可以通过名称将快捷键列表并运行 若您有命令行工具或脚本 它们可以通过这个界面 与Shortcuts集成 总结一下 Mac现在支持Shortcuts 无论您的App属于什么类型 您都应该尝试加入 Shortcuts的生态系统 为您的App添加操作之后 App在用户手中能焕发出无限新用法 Shortcuts让用户能 创造性地使用您的App 通过App里的操作 用户们所能构建出的奇妙Shortcuts 一定会让您大开眼界 [律动感的音乐]
-
-
17:10 - Adding Intent dispatch method in SwiftUI
import SwiftUI import Intents @main struct SouperTaskApp: App { @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate var body: some Scene { WindowGroup { ContentView() } } } class AppDelegate: NSObject, NSApplicationDelegate { func application(_ application: NSApplication, handlerFor intent: INIntent) -> Any? { } }
-
18:32 - Resolve intent
class IntentHandler: NSObject, CreateTaskIntentHandling { func resolveTitle(for intent: CreateTaskIntent, with completion: @escaping (INStringResolutionResult) -> Void) { guard let title = intent.title, !title.isEmpty else { return completion(.needsValue()) } return completion(.success(with: title)) } func resolveDueDate(for intent: CreateTaskIntent, with completion: @escaping (CreateTaskDueDateResolutionResult) -> Void) { guard let dateComponents = intent.dueDate else { return completion(.needsValue()) } return completion(.success(with: dateComponents)) } ... }
-
19:37 - Date range validation in dueDate resolve method
func resolveDueDate(for intent: CreateTaskIntent, with completion: @escaping (CreateTaskDueDateResolutionResult) -> Void) { guard let dateComponents = intent.dueDate, let dueDate = Calendar.current.date(from: dateComponents) else { return completion(.needsValue()) } if dueDate < Date() { return completion(.unsupported(forReason: .invalidDate)) } return completion(.success(with: dateComponents)) }
-
20:40 - Handle intent
class IntentHandler: NSObject, CreateTaskIntentHandling { func handle(intent: CreateTaskIntent, completion: @escaping (CreateTaskIntentResponse) -> Void) { let title = intent.title! let dueDate = intent.dueDate! let task = createTask(name: title, due: dueDate) let response = CreateTaskIntentResponse(code: .success, userActivity: nil) response.task = task completion(response) } }
-
25:39 - Running Shortcut from AppleScript
tell application "Shortcuts Events" run the shortcut whose name is "Make GIF" end tell
-
25:49 - Using scripting bridge
import ScriptingBridge @objc protocol ShortcutsEvents { @objc optional var shortcuts: SBElementArray { get } } @objc protocol Shortcut { @objc optional var name: String { get } @objc optional func run(withInput: Any?) -> Any? } extension SBApplication: ShortcutsEvents {} extension SBObject: Shortcut {} guard let app: ShortcutsEvents = SBApplication(bundleIdentifier: "com.apple.shortcuts.events"), let shortcuts = app.shortcuts else { print("Couldn't access shortcuts") return } guard let shortcut = shortcuts.object(withName: "Make GIF") as? Shortcut else { print("Shortcut doesn't exist") return } _ = shortcut.run?(withInput: nil)
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。