iOS中如何修改本地/推送通知的点击与长按交互行为
iOS中如何修改本地/推送通知的点击与长按交互行为
嘿,这个需求确实有点反常规,但完全可以实现!我来给你拆解具体步骤:
第一步:创建并配置通知内容扩展(实现点击通知显示交互预览)
首先你需要一个通知内容扩展(UNNotificationContentExtension),这是实现交互式通知的核心,用来展示你想要的预览和交互控件。
- 打开Xcode,点击
File -> New -> Target,选择Notification Content Extension,命名后完成创建(记得激活这个Target的签名)。 - 打开扩展的
Info.plist,找到NSExtensionAttributes节点,添加/修改以下配置:UNNotificationExtensionCategory:设置一个自定义类别ID,比如ReverseNotificationCategory(后面注册通知时要对应上)UNNotificationExtensionDefaultContentHidden:设为YES,这样默认的通知文本会被隐藏,点击通知直接显示你的扩展界面UNNotificationExtensionInitialContentSizeRatio:可以设为1.0,让扩展界面占满通知区域
第二步:在主APP中注册自定义通知类别
在主APP的启动代码里(比如AppDelegate的didFinishLaunchingWithOptions或SceneDelegate的scene(_:willConnectTo:options:)),注册我们的自定义通知类别,同时添加一个“打开APP”的快捷动作:
func setupNotificationCategory() { let center = UNUserNotificationCenter.current() // 创建「打开APP」的快捷动作,设置为前台触发 let openAppAction = UNNotificationAction( identifier: "OpenAppAction", title: "打开应用", options: [.foreground] // 点击后直接打开APP到前台 ) // 关联我们的自定义类别和动作 let reverseCategory = UNNotificationCategory( identifier: "ReverseNotificationCategory", actions: [openAppAction], intentIdentifiers: [], options: [] ) // 注册类别 center.setNotificationCategories([reverseCategory]) }
第三步:拦截默认点击行为,让点击停留在扩展界面
默认情况下,用户点击通知会直接打开APP,我们需要在主APP的通知响应方法里拦截这个行为:
在AppDelegate或SceneDelegate中实现UNUserNotificationCenterDelegate的方法:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { // 判断是否是默认的通知点击动作 if response.actionIdentifier == UNNotificationDefaultActionIdentifier { // 不执行打开APP的逻辑,让通知中心保持显示扩展界面 completionHandler() // 如果你不想让APP被唤醒到后台,可以在这里做额外处理,比如直接返回 return } // 如果是点击了「打开APP」的快捷动作,交给系统默认处理(打开APP) if response.actionIdentifier == "OpenAppAction" { completionHandler() return } // 其他动作的处理逻辑(如果有的话) completionHandler() }
第四步:处理长按通知的逻辑
iOS系统的长按通知本身是用来唤起通知的交互预览和快捷动作的,我们没法直接把长按映射成“打开APP”,但可以优化体验:
- 当用户长按通知时,系统会自动显示我们之前配置的「打开APP」快捷动作,用户点击这个动作就能直接打开APP。
- 如果你想要更接近“长按直接打开APP”的体验,可以在通知扩展的界面里添加一个长按手势识别器,当用户在扩展界面上长按的时候,调用
extensionContext?.open(_:completionHandler:)来打开主APP:
// 在通知扩展的ViewController里添加长按手势 override func viewDidLoad() { super.viewDidLoad() let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress)) view.addGestureRecognizer(longPressGesture) } @objc private func handleLongPress() { // 打开主APP,替换成你的APP自定义URL Scheme if let url = URL(string: "yourappscheme://") { extensionContext?.open(url, completionHandler: nil) } }
注意:这里需要在主APP的Info.plist里配置自定义URL Scheme,比如yourappscheme,这样扩展才能通过URL唤起主APP。
第五步:发送通知时关联自定义类别
不管是本地通知还是远程推送,都需要在payload里指定我们的自定义类别,并且开启可变内容:
- 本地通知示例:
let content = UNMutableNotificationContent() content.title = "测试通知" content.body = "点击查看交互,长按打开APP" content.categoryIdentifier = "ReverseNotificationCategory" content.mutableContent = true // 必须开启,才能加载通知扩展 let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false) let request = UNNotificationRequest(identifier: "TestReverseNotification", content: content, trigger: trigger) UNUserNotificationCenter.current().add(request)
- 远程推送Payload示例(JSON格式):
{ "aps": { "alert": { "title": "测试通知", "body": "点击查看交互,长按打开APP" }, "category": "ReverseNotificationCategory", "mutable-content": 1 } }
这样配置后,就能实现你要的效果:点击通知直接显示交互式扩展界面,长按通知(或在扩展界面上长按)可以打开主APP啦!
备注:内容来源于stack exchange,提问作者iOSCoder
相关产品推荐
相关产品推荐

