Feature your actions in the Shortcuts app
System Frameworks 进阶 22m

在快捷指令 App 中展示你的操作

Feature your actions in the Shortcuts app

2020年6月25日

在 Apple 官方观看视频

一句话判断

Shortcuts App 在 iOS 14 中有了全面改版,如果你的 App 已经支持 SiriKit 或 Intents,做好参数配置和发现优化就能让你的操作被更多用户发现和使用。

这场 Session 讲了什么

iOS 14 对快捷指令(Shortcuts)App 进行了重大重新设计。新的 Shortcuts App 采用了更清晰的分类结构,会自动发现已安装 App 的所有可用操作。Session 重点讲解了开发者如何让自己的 Intent 操作在 Shortcuts App 中获得更好的展示效果,包括参数配置、动态选项、交互预览等。

Apple 详细介绍了如何通过 Intent Definition File 配置参数的显示方式、如何提供动态选项列表(比如让用户从服务器获取最新的播放列表)、如何设置参数之间的依赖关系(选了专辑后才显示歌曲选项),以及如何让你的操作出现在 Shortcuts 的推荐分类中。

值得深挖的点

参数依赖与动态选项

这是 Shortcuts 集成中最有技术深度的部分。当你的 Intent 有多个参数时,参数之间可能存在依赖关系。比如”选择歌单 -> 选择歌曲”,歌曲列表取决于用户选了哪个歌单。通过 INParameter 的依赖关系配置,Shortcuts App 会在用户选择了第一个参数后才去查询第二个参数的选项,体验上就像原生 App 一样流畅。

Shortcuts 自动发现机制

iOS 14 的 Shortcuts App 会扫描所有已安装 App 的 Intent Definition,自动展示所有可用的操作。你不需要做额外的注册工作。但你可以通过 INShortcutsuggestedInvocationPhrase 和系统分类来提高发现性。Apple 建议为每个操作提供清晰的中文名称和描述,因为用户会在 Shortcuts 的列表中直接看到这些文本。

代码片段

配置 Intent 参数的动态选项

场景:为音乐 App 的”播放歌单”操作提供动态歌单列表。

import Intents

class PlaylistIntentHandler: NSObject, PlayPlaylistIntentHandling {
    
    // 提供歌单的动态选项列表
    func providePlaylistOptionsCollection(
        for intent: PlayPlaylistIntent,
        with completion: @escaping (INObjectCollection<Playlist>, Error?) -> Void) {
        
        // 从服务器获取用户的所有歌单
        MusicService.fetchPlaylists { playlists in
            let items = playlists.map { playlist in
                Playlist(identifier: playlist.id,
                         display: playlist.name)
            }
            
            let collection = INObjectCollection(items: items)
            completion(collection, nil)
        }
    }
    
    func handle(intent: PlayPlaylistIntent,
                completion: @escaping (PlayPlaylistIntentResponse) -> Void) {
        guard let playlist = intent.playlist else {
            completion(.failure(error: "未选择歌单"))
            return
        }
        
        // 开始播放选中的歌单
        MusicPlayer.shared.play(playlistId: playlist.identifier)
        completion(.success(result: playlist))
    }
}

设置参数之间的依赖关系

场景:歌单选择后动态更新歌曲选项。

class SongIntentHandler: NSObject, PlaySongIntentHandling {
    
    // 声明参数依赖:歌曲选项依赖于歌单参数
    static func playlistChoices(for intent: PlaySongIntent) -> [INParameter] {
        // 告诉系统 playlist 参数的选择会影响 song 参数的选项
        return [INParameter(parameters: \PlaySongIntent.playlist)]
    }
    
    // 提供歌曲的动态选项(依赖于已选择的歌单)
    func provideSongOptionsCollection(
        for intent: PlaySongIntent,
        with completion: @escaping (INObjectCollection<Song>, Error?) -> Void) {
        
        guard let playlistId = intent.playlist?.identifier else {
            completion(INObjectCollection(items: []), nil)
            return
        }
        
        // 根据选中的歌单获取歌曲列表
        MusicService.fetchSongs(playlistId: playlistId) { songs in
            let items = songs.map { song in
                Song(identifier: song.id, display: song.title)
            }
            completion(INObjectCollection(items: items), nil)
        }
    }
}

创建 INShortcut 并设置建议短语

场景:为 Shortcuts App 创建可发现的快捷方式。

import Intents

// 从 Intent 创建 Shortcut
func createShortcuts() {
    // 方法一:从 Intent 创建
    var intent = PlayPlaylistIntent()
    intent.playlist = Playlist(identifier: "favorites",
                               display: "我的收藏")
    intent.suggestedInvocationPhrase = "播放我的收藏"
    
    if let shortcut = INShortcut(intent: intent) {
        // 捐赠给系统,让 Siri 学会推荐
        let interaction = INInteraction(intent: intent, response: nil)
        interaction.donate { error in
            if let error = error {
                print("捐赠快捷方式失败: \(error)")
            }
        }
    }
    
    // 方法二:从 NSUserActivity 创建
    let activity = NSUserActivity(activityType: "com.yourapp.play")
    activity.title = "播放音乐"
    activity.isEligibleForSearch = true
    activity.isEligibleForPrediction = true
    activity.suggestedInvocationPhrase = "播放音乐"
    activity.becomeCurrent()
}

最佳实践

已有项目:如果你的 App 已经支持 SiriKit,确保所有的 Intent 参数都配置了正确的 display name 和描述。检查 Intent Definition File 中的参数顺序——排在前面的参数会先被用户填写。为常用操作设置合理的 suggestedInvocationPhrase

新项目:从产品角度规划哪些功能适合暴露为 Shortcuts 操作。优先选择”一个输入 -> 一个输出”的简单操作,比如”播放某歌单”、“发送消息给某人”。复杂的操作链用 Shortcuts 的 Workflow 功能组合即可。

还有什么值得关注

  • Shortcuts 现在支持文件夹分类,你的操作可以通过 Intent Category 自动归入对应文件夹。
  • iOS 14 新增了”快捷指令”桌面小组件,用户可以把常用操作放在主屏,这进一步放大了 Shortcuts 集成的价值。
  • 动态选项支持分页加载,如果你的选项列表很长,使用 INObjectCollection 的分页能力避免一次性加载过多数据。
WWDC 2020