F550f26c04e412c8814c6c85aaffdf27
【WWDC21 10264】让你的 App 支持快速备忘录

作者:希徳, iOS / 前端开发者,关注效率和流程优化。曾就职于网易严选,负责 Web容器、技术栈优化、工程效能和流程改进工作。

审核:JonyFang,iOS 开发,老司机技术周报编辑,就职于哔哩哔哩直播部门

快速备忘录是什么?

快速备忘录本质是备忘录应用的一个扩展,它的目标是方便用户在已支持快速备忘录功能的 App 里(如 Safari)快速记录内容,目前支持内容的格式包括: 文字、图片、地图、链接(以卡片的形式)。并且在再次回到上次发生过记录行为的地方会有高亮提示(称之为快速备忘录建议),方便回顾和修改整理。再搭配这次 iOS 15/ macOS Monterey 升级的备忘新功能——支持的 @能力、# tag 、搜索、分享能力,让 Apple 设备上的资料整理变的前所未有的高效。

快速备忘录如何使用

我们以在 macOS Monterey 上使用为例(本 session 里是使用支持 Apple Pencil 的 iPad 演示,原理一样)。任一设备上创建的 Notes 都是跨平台共享的,在 iPad 上创建的 Notes 可以在 macOS 、iPhone 上看到。那么如何使用快速备忘录呢?

  • 使用场景一:桌面唤醒。
    按住 Command 键,将鼠标置于整个屏幕右下角(双屏的用户主屏幕的右下角),此时会展示小卡片,

桌面唤醒

桌面唤醒

这个行为是可以配置的,路径是
Preferences -> Mission Control而不是Preferences -> Screen SaverScreen Hot Corners.
需要同时按住 Command 键

需要同时按住 Command 键

  • 方法二:在 Safari 里唤醒(目前 beta 版本只有 Safari 支持)。
    也有两种方式,一种是选中文字(注意不能选中编辑状态的文字),点击右键菜单,
    选中 New Quick Note, Add To Quick Note,此时会唤起右下角悬浮卡片(此时不能打开 Notes App,否则只会直接打开 Notes App,而不是悬浮卡片)。
    选择新建 A
    选择新建 A

    可以看到对双屏用户,悬浮菜单的位置不对,我在上面的屏幕操作,悬浮卡片在下面的屏幕。点击悬浮卡片,展开悬浮的备忘编辑器(这时候悬浮编辑器又是在上面的屏幕,位置是对的)。

这里的Add To Quick Note 行为不符合常理,按照我的理解:应该是添加到这个页面已有的备忘才对;而事实的行为是它会添加的你上一个备忘里,没有区分是否是相同 URL 的页面里选中的文字(猜测和 Safari 15 对 Quick Notes 的适配逻辑有关系)

第二种添加方式,在新版本浏览器的地址栏,点击更多按钮,选中Create Quick Note,

很遗憾,点击后在我的电脑上没有什么反应,什么都没有发生,期待下次 beta 能够 work。

快速备忘录和备忘录的关系

简单是说 快速备忘录是备忘录的一个快捷入口,被保存的快速备忘录最后会变成备忘录的一个新分组Quick Notes,展示在所有分组最上面;所有 Quick Notes 和其他备忘录里的 Notes 没有区别(除了在 Notes App 里不能被锁定外)。另外本次 macOS Menterey 还可以通过 iPhone 在备忘里增加手写体,保存为图片和 Apple Pencil 的输出一样。

快速备忘录和备忘录 App 是独立的窗体,如果你已经打开了 A,想回到备忘录 App,iPad 上可以点击右上角工具栏里的 Notes 图标,但是在 macOS 上我没找到任何途径,除非手动在菜单里选择 Window -> Notes

快速备忘录支持的格式包括文字、图片、地图、链接(以卡片的形式),而备忘录 App 支持的格式远不止如此,Objective-c 源码、mp4 源文件等大部分支持 URI 访问的资源都可以支持,他们会被当作附件的方式保存在备忘的文件系统里。

更牛的是这些视频和源码都会被自动同步到云端(多端冲突处理逻辑待查),用户完全不用关心被保存在哪儿,所以可以放心的把它当作富邮件客户端使用了。

快速备忘录的工作原理

快速备忘录技术上沿用里 NSUserActivity 的接口,而 NSUserActivity 之前被广泛使用在其他保持 App 的运行态的功能里,如 Handoff \ Universal Link \ Widget 打开 Host App 流程等。源 App 将现在正在发生的事件,用 NSUserActivity 的类型封装这些状态,生成实例,注册到 User activity system系统。而 User activity system系统管理着这些 NSUserActivity 实例,传递给目标 App,目标 App 接收到这些 NSUserActivity 实例后作出相应的逻辑处理——相信上面的这些步骤你已经很熟悉了。
Handoff 之前到流程

Handoff 之前到流程

当快速备忘录加入到 User activity system系统后,系统还会把这些 NSUserActivity 实例同时发送给快速备忘录,这时候会触发你的 App 的 Add Link 菜单和快速备忘录建议。
加入快速备忘录后到流程
加入快速备忘录后到流程

支持快速备忘录的关键字段

快速备忘录复用了 NSUserActivity 对象里业已存在的 3 个字段来支持功能实现;

  • targetContentIdentifier
  • persistentIdentifier
  • webpageURL

不同的功能使用不同的字段;

  1. targetContentIdentifier也用于 App 的状态恢复,服务于多窗口、多任务时的内容接力;

  2. persistentIdentifier也用于 Spotlight 里用来标识应用的内容,正如其名称所指,它服务于被持久化的内容,系统还提供了根据此字段删除 NSUserActivity 实例的接口;

  3. webpageURL表明源 App 活动内容是个网页,用于 HandoffUniversal Link等场景;

为了能够支持快速备忘录能够实现跨平台的体验,以上字段的值需要满足一定的要求;

  1. 唯一性,在多次内容的收集中需要有不同的 id;需要注意不要和其他 App 的值冲突;
  2. 全局性,除了考虑当前设备外,还需要考虑多个设备上相同内容里生成的值的唯一性;
  3. 稳定性,今天在本 App 里生成的内容,在半年之后,重新打开相同界面能够使用相同的标识来保存快速备忘录。这也是快速备忘录建议能够出现的前提条件。如果你用过类似 Safari 插件 Liner或者 LightNote for macOS, 你在某个网页之前收集的文字,下次打开后会高亮显示,容许你再次编辑修改。

如何配置 App 支持 快速备忘录

下面我新建 QuickNote 的 iOS 应用来演示如何配置。

1. 声明支持 ActivityType 类型

info.plist 文件里声明 ActivityType,以让User activity system系统过滤掉本 App 不关心的 NSUserActivity 的实例,也防止信息泄漏。通常这些可以使用 bundleId 作为前缀作为唯一性保证。

声明支持的活动类型

声明支持的活动类型

2. 注册本 App 的活动状态

在合适的时机,创建描述当前活动状态的 NSUserActivity 对象实例,注册到User activity system系统。

```swift
class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    self.view.backgroundColor = .red

    // 创建 activity
    let activity = NSUserActivity (activityType: "me.hite.app.QuickNote.type1")
    activity.title = "I am in ViewController and background color is red."
    // persistentIdentifier 也可以,这样 Spotlight 也可以搜到
    activity.persistentIdentifier = "me.hite.app.QuickNote.type1_\(ViewController.self)"
    activity.userInfo = ["timestamp": "\(Date.now)", "text": "我是支持 Spotlight 的#吃饭#下雨"]
top Created with Sketch.