WWDC Quick Look 💓 By SwiftGGTeam
Send communication and Time Sensitive notifications

Send communication and Time Sensitive notifications

观看原视频

Highlight

iOS 15 引入了四种通知中断级别(Passive、Active、Time Sensitive、Critical),并新增 Communication Notifications 机制,让消息和通话类通知能穿透 Focus 和通知摘要,同时通过 SiriKit Intents 将通知与联系人、Shortcuts 深度整合。

核心内容

通知的视觉升级

以前通知操作按钮只有文字,用户需要阅读才能理解每个按钮的作用。

iOS 15 的通知有了新外观,更突出内容和媒体。操作按钮现在可以附带图标。用 UNNotificationActionIcon 创建系统图标或模板图标,再传给 UNNotificationAction 的构造器。展开通知时,图标会显示在按钮旁边,一眼就能识别操作含义。

同时,通知中的应用图标尺寸变大了,需要确保提供高分辨率图标。

系统管理工具:通知摘要与 Focus

用户每天收到几十条通知,锁屏被不断打断。iOS 15 引入了两个管理工具。

通知摘要:非紧急通知可以在预设时间(如早上 8 点、晚上 6 点)批量汇总展示,减少主动打断次数。被收入摘要的通知仍会出现在锁屏通知列表中。开发者可以通过设置 relevanceScore 让重要通知排在摘要顶部。

Focus:用户可以根据活动或时间段设置 Focus(如工作、睡眠、阅读),只允许特定应用和联系人发送打断性通知。例如工作 Focus 下,只有 Mail、Messages 和同事的直接通信能穿透。

中断级别:让通知”懂事”一点

以前所有通知要么都响、要么都静音,没有中间状态。iOS 15 引入了 UNNotificationInterruptionLevel,分四个级别:

级别行为穿透 Focus/摘要适用场景
Passive静默投递,不亮屏不响铃餐厅推荐、新剧集上线
Active响铃+亮屏(默认行为)体育比分、直播提醒
Time Sensitive响铃+亮屏是(需用户允许)账户安全、包裹送达
Critical响铃+亮屏,绕过静音开关恶劣天气、安全警报

Passive 级别适合那些”不需要立刻看,但有空时该看看”的通知。Time Sensitive 需要用户在 Xcode 中开启对应 Capability,且不能滥用——用户可以选择关闭某个应用的 Time Sensitive 权限。

Communication Notifications:让消息通知更像系统消息

来自人的通信(电话、消息)理应比普通通知更受重视。iOS 15 允许应用通过 SiriKit Intents 将通知标记为通信通知,获得以下升级体验:

  • 显示发件人头像
  • 标题和副标题标准化、本地化
  • Siri 在 AirPods、HomePod、CarPlay 上自动播报内容
  • 能穿透 Focus 和通知摘要(基于用户与联系人的互动历史)
  • 与系统联系人关联,出现在 Share Sheet 和 Spotlight 建议中

实现方式是在 UNNotificationServiceExtension 中,用 INSendMessageIntentINStartCallIntent 更新通知内容,并捐赠(donate)交互。

详细内容

为通知操作添加图标

01:57

let likeActionIcon = UNNotificationActionIcon(systemImageName: "hand.thumbsup")
let likeAction = UNNotificationAction(
    identifier: "like-action",
    title: "Like",
    options: [],
    icon: likeActionIcon
)

let commentActionIcon = UNNotificationActionIcon(templateImageName: "text.bubble")
let commentAction = UNTextInputNotificationAction(
    identifier: "comment-action",
    title: "Comment",
    options: [],
    icon: commentActionIcon,
    textInputButtonTitle: "Post",
    textInputPlaceholder: "Type here…"
)

let category = UNNotificationCategory(
    identifier: "update-actions",
    actions: [likeAction, commentAction],
    intentIdentifiers: [],
    options: []
)

关键点:

  • UNNotificationActionIcon 支持系统 SF Symbol(systemImageName)或应用内模板图(templateImageName
  • UNTextInputNotificationAction 是带输入框的操作,适合评论、回复场景
  • 图标在通知展开后显示在操作按钮左侧

设置中断级别

08:19

本地通知设置 Passive 级别:

let content = UNMutableNotificationContent()
content.title = "Passive"
content.body = "I'm a passive notification, so I won't interrupt you."
content.interruptionLevel = .passive

let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
let request = UNNotificationRequest(
    identifier: "passive-request-example",
    content: content,
    trigger: trigger
)

推送通知设置 Passive 级别:

{
    "aps": {
        "alert": {
            "title": "Passive",
            "body": "I'm a passive notification, so I won't interrupt you."
        },
        "interruption-level": "passive"
    }
}

关键点:

  • interruptionLevelUNMutableNotificationContent 的新属性
  • 推送 payload 中用 "interruption-level" 键,值可以是 "passive""active""time-sensitive""critical"
  • 不设置时默认是 active

Time Sensitive 通知

11:13

let content = UNMutableNotificationContent()
content.title = "Urgent"
content.body = "Your account requires attention."
content.interruptionLevel = .timeSensitive

let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0, repeats: false)
let request = UNNotificationRequest(
    identifier: "time-sensitive-example",
    content: content,
    trigger: trigger
)

推送版本:

{
    "aps": {
        "alert": {
            "title": "Urgent",
            "body": "Your account requires attention."
        },
        "interruption-level": "time-sensitive"
    }
}

关键点:

  • 需要在 Xcode 的 Signing & Capabilities 中开启 Time Sensitive Notifications
  • 滥用会导致用户关闭该应用的 Time Sensitive 权限
  • 适合账户安全提醒、包裹送达、用药提醒等真正紧急的场景

Communication Notification:消息通知

16:08

UNNotificationServiceExtension 中处理推送通知:

func didReceive(
    _ request: UNNotificationRequest,
    withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
) {
    let incomingMessageIntent: INSendMessageIntent = // 从 payload 解析
    let interaction = INInteraction(intent: incomingMessageIntent, response: nil)
    interaction.direction = .incoming
    interaction.donate(completion: nil)

    do {
        let messageContent = try request.content.updating(from: incomingMessageIntent)
        contentHandler(messageContent)
    } catch {
        // Handle error
    }
}

关键点:

  • UNNotificationContentProviding 协议是连接 Intents 和通知内容的桥梁
  • interaction.direction 对通知必须是 .incoming
  • donate() 让 Siri 学习用户与哪些人有互动,从而优化 Focus 穿透建议

创建 INPerson 和 INSendMessageIntent

18:29

let person = INPerson(
    personHandle: handle,
    nameComponents: nameComponents,
    displayName: displayName,
    image: image,
    contactIdentifier: contactIdentifier,
    customIdentifier: customIdentifier,
    aliases: nil,
    suggestionType: suggestionType
)

let intent = INSendMessageIntent(
    recipients: [person2],
    outgoingMessageType: .outgoingMessageText,
    content: content,
    speakableGroupName: speakableGroupName,
    conversationIdentifier: conversationIdentifier,
    serviceName: serviceName,
    sender: person1,
    attachments: nil
)

let interaction = INInteraction(intent: intent, response: nil)
interaction.direction = .incoming

关键点:

  • INPerson 的每个参数(contactIdentifiercustomIdentifierimage 等)都会提升用户体验
  • conversationIdentifier 用于将同一对话的通知归组
  • 发件人通过 sender 参数指定,会在通知标题中显示

捐赠 Outgoing Intents

17:48

用户在应用内主动发送消息时,也要捐赠 Intent:

func sendMessage(...) {
    let intent: INSendMessageIntent = // 创建 Intent
    let interaction = INInteraction(intent: intent, response: nil)
    interaction.direction = .outgoing
    interaction.donate(completion: nil)
}

关键点:

  • Outgoing donations 帮助 Siri 判断哪些联系人应该被建议穿透 Focus
  • 只有 Outgoing donations 会被用于联系人建议,避免垃圾来电干扰
  • 需要在 Info.plist 的 NSUserActivityTypes 中添加对应的 Intent 类型,或实现 Intents Extension

核心启发

  1. 为不同场景选择合适的中断级别

    • 做什么:将应用内所有通知按紧急程度分类,分别设置 Passive、Active、Time Sensitive
    • 为什么值得做:减少用户被打扰的次数,提升重要通知的到达率。用户更愿意保留那些”懂事”的应用的通知权限
    • 怎么开始:审计现有通知,把推荐类、更新类改为 Passive,把安全提醒改为 Time Sensitive。入口 API 是 UNMutableNotificationContent.interruptionLevel
  2. 为社交/通讯应用接入 Communication Notifications

    • 做什么:让应用内的私信、群聊、通话通知显示头像、穿透 Focus、被 Siri 播报
    • 为什么值得做:系统级体验升级,用户感知明显。与系统联系人整合后,Share Sheet 和 Spotlight 都会出现你的应用
    • 怎么开始:添加 Notification Service Extension,在 didReceive 中用 INSendMessageIntent 更新通知内容。同时在前台用户发消息时捐赠 Outgoing Intent
  3. 利用 relevanceScore 优化通知摘要排序

    • 做什么:为通知设置相关性分数,让最重要的通知出现在摘要顶部
    • 为什么值得做:通知摘要会折叠多条通知,只有分数高的才会被突出展示
    • 怎么开始:设置 UNMutableNotificationContent.relevanceScore,范围 0.0 到 1.0
  4. 为通知操作添加图标

    • 做什么:给所有自定义通知操作配上 SF Symbol 图标
    • 为什么值得做:图标比文字更直观,用户无需阅读就能识别操作含义
    • 怎么开始:创建 UNNotificationActionIcon(systemImageName:) 并传入 UNNotificationAction 的构造器

关联 Session

评论

GitHub Issues · utterances