10.推送的扩展能力 — 打造安全的通知体验

推送的扩展能力 --- 打造安全的通知体验

1. 什么是 Notification Service Extension?

Notification Service Extension(通知服务扩展,简称 NSE)是 iOS 10 及以后系统引入的一种特殊的 App 扩展,它允许开发者在推送通知到达设备时对通知的内容进行修改和处理,从而实现丰富的推送通知效果。通过 NSE,App 可以在通知展示给用户之前,动态地修改通知的标题、内容,或者添加附件(图片、音频、视频等),增强用户体验。

简单来说,NSE 介于 APNs 推送服务器和系统通知显示之间,拦截并"加工"通知内容,使推送通知更加生动和个性化。

2. Notification Service Extension 的工作流程

  1. 推送通知到达设备 APNs 发送包含 mutable-content: 1 标记的推送通知给用户设备。
  2. 系统触发 Notification Service Extension 系统检测到通知 payload 中包含 mutable-content,自动唤醒 NSE 扩展执行。
  3. NSE 执行处理逻辑 NSE 的入口方法 didReceive(_:withContentHandler:) 被调用,开发者在这里可以修改通知内容或下载附件等。
  4. 调用 Content Handler 完成通知修改 开发者处理完后调用 contentHandler,系统将修改后的通知内容交给通知中心显示给用户。
  5. 超时处理 NSE 有约 30 秒的执行时间限制,超时系统会显示原始通知。

3. 使用场景举例

  • 添加富媒体附件:图片、GIF、音频、视频等
  • 自定义通知内容:根据业务需求,动态修改通知标题、正文
  • 内容解密:对推送加密内容进行解密后再展示
  • 下载远程资源:从网络拉取相关内容,提升通知表现力
  • 统计或日志上报:通知展示前埋点统计

1. 修改通知标题和正文

less 复制代码
 override func didReceive(_ request: UNNotificationRequest,
                          withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
    let bestContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
    bestContent?.title = "【重要提示】" + (bestContent?.title ?? "")
    bestContent?.body += "\n请及时查看。"
    contentHandler(bestContent ?? request.content)
 }

2. 动态添加本地附件资源

php 复制代码
 if let url = Bundle.main.url(forResource: "localImage", withExtension: "jpg") {
    do {
        let attachment = try UNNotificationAttachment(identifier: "image", url: url, options: nil)
        bestContent?.attachments = [attachment]
    } catch {
        print("附件添加失败: (error)")
    }
 }
 contentHandler(bestContent ?? request.content)

4. 如何配置 Notification Service Extension

  1. 新建 Target 在 Xcode 中选择 File > New > Target,选择 Notification Service Extension 模板,填写名称如 MyAppNotificationService

  2. 修改 Info.plist 默认系统会生成对应的 Info.plist,确认 NSExtension 字典配置正确。一般无需手动修改。

  3. 配置推送 Payload 需要在 APNs 推送的 payload 中添加字段:

    css 复制代码
     {
      "aps": {
        "alert": {
          "title": "标题",
          "body": "内容"
        },
        "mutable-content": 1
      },
      "customKey": "自定义数据"
     }

    mutable-content: 1 是触发 NSE 的关键。

  4. 实现处理逻辑 在 NSE 入口类 NotificationService 中重写:

    typescript 复制代码
     override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
     ​
        guard let bestAttemptContent = bestAttemptContent else {
            contentHandler(request.content)
            return
        }
     ​
        // 示例:修改标题
        bestAttemptContent.title = "(bestAttemptContent.title) [修改]"
     ​
        // 示例:下载附件(异步操作需要调用contentHandler)
        if let urlString = bestAttemptContent.userInfo["image-url"] as? String,
            let url = URL(string: urlString) {
            downloadAttachment(from: url) { attachment in
                if let attachment = attachment {
                    bestAttemptContent.attachments = [attachment]
                }
                contentHandler(bestAttemptContent)
            }
        } else {
            contentHandler(bestAttemptContent)
        }
     }
  5. 处理超时 实现:

    csharp 复制代码
     override func serviceExtensionTimeWillExpire() {
        if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
     }

    保障超时后仍能显示内容。

5. 常见问题与注意事项

  • NSE 执行时间限制 通常只有约 30 秒,超时系统自动调用 serviceExtensionTimeWillExpire(),务必保证处理逻辑高效。
  • 推送 Payload 大小限制 推送负载有限制,NSE 下载远程资源可以突破内容限制,但附件大小不能太大,通常推荐几十 MB 以内。
  • 用户权限 只有当用户允许推送通知且 App 已启用通知权限时,NSE 才会被调用。
  • 调试技巧 可以通过 Xcode 的 Scheme 设置启动 NSE 调试,或使用真机配合 Xcode 控制台调试。
  • 模拟器限制 模拟器对推送通知支持有限,尤其是扩展调试,最好在真机上调试。

6. 总结

Notification Service Extension 让开发者有能力在通知内容展示前对通知进行安全、灵活的动态处理,提升通知内容的准确性和用户体验。 它与 Notification Content Extension 搭配使用,可以共同打造出既个性化又安全的推送体系。

相关推荐
大熊猫侯佩6 小时前
侠客行・iOS 26 Liquid Glass TabBar 破阵记
ios·swiftui·swift
qixingchao1 天前
iOS SwiftUI 动画开发指南
ios·swiftui·swift
大熊猫侯佩1 天前
猿族代码战记:Mutex 升级版——守护 Swift 并发的“香蕉仓库”
swiftui·swift·apple
大熊猫侯佩1 天前
Thread.sleep 与 Task.sleep 终极对决:Swift 并发世界的 “魔法休眠术” 揭秘
ios·swift·apple
大熊猫侯佩1 天前
【大话码游之 Observation 传说】下集:破咒终局了,天眼定乾坤
ios·swift·apple
大熊猫侯佩1 天前
【大话码游之 Observation 传说】中集:仙流暗涌,计数迷踪现
ios·swift·apple
大熊猫侯佩1 天前
寥寥几行代码实现 SwiftUI 超丝滑弹窗转场动画
ios·swiftui·swift
请叫我飞哥@1 天前
Apple授权登录开发流程
ios·swift