iOS应用关闭时点击本地通知无法获取userInfo问题求助
嘿,我来帮你搞定这个App关闭时点击通知拿不到userInfo的问题!这种情况我之前也碰到过,大概率是代理设置或者方法实现的细节没处理到位,咱们一步步排查:
1. 先确认代理的设置位置(iOS 13+关键!)
如果你的App是基于iOS 13及以上开发的,用了SceneDelegate,那一定要在SceneDelegate里设置UNUserNotificationCenter的代理,而不是只在AppDelegate里设置。因为App完全关闭后点击通知启动,系统会先走SceneDelegate的启动逻辑,代理设置晚了就会错过回调。
正确的设置方式(SceneDelegate里):
class SceneDelegate: UIResponder, UIWindowSceneDelegate, UNUserNotificationCenterDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // 必须在这里就设置代理,别等到后面! UNUserNotificationCenter.current().delegate = self // 额外:如果是点击通知直接启动App,这里也能提前拿到响应(可选) if let notificationResponse = connectionOptions.notificationResponse { self.handleNotification(response: notificationResponse) } guard let _ = (scene as? UIWindowScene) else { return } } // 你的其他代码... }
如果是iOS 12及以下的项目,就在AppDelegate的application(_:didFinishLaunchingWithOptions:)里设置代理。
2. 完整实现代理方法,别漏了completionHandler
你提到的userNotificationCenter(_:didReceive:withCompletionHandler:)方法,必须完整实现,而且一定要调用completionHandler(),否则系统会认为你没处理完这个通知,后续逻辑可能不会正常触发。
完整的方法示例:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { // 这里拿到你的userInfo let userInfo = response.notification.request.content.userInfo print("成功获取到userInfo: \(userInfo)") // 这里写你的业务逻辑,比如跳转对应页面、展示内容等 handleNotification(response: response) // 必须调用这个!告诉系统你处理完了 completionHandler() } // 抽离处理逻辑,代码更清晰 private func handleNotification(response: UNNotificationResponse) { let userInfo = response.notification.request.content.userInfo // 比如根据userInfo里的id跳转详情页 if let targetId = userInfo["target_id"] as? String { // 执行跳转逻辑 } }
3. 检查通知请求的userInfo是否正确设置
有时候不是回调的问题,是你创建通知时没把userInfo正确塞进去。创建通知内容的时候要确保:
let content = UNMutableNotificationContent() content.title = "你的通知标题" content.body = "你的通知内容" // 这里一定要正确设置userInfo,键值对要符合你后续解析的格式 content.userInfo = ["target_id": "12345", "type": "reminder"] // 后续创建通知请求的代码... let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger) UNUserNotificationCenter.current().add(request) { error in if let error = error { print("添加通知失败: \(error)") } }
4. 别忘了遵循协议!
不管是在SceneDelegate还是AppDelegate里,都要确保类声明时加上UNUserNotificationCenterDelegate协议,否则代理方法不会被系统调用。比如:
// SceneDelegate的正确声明 class SceneDelegate: UIResponder, UIWindowSceneDelegate, UNUserNotificationCenterDelegate { ... } // AppDelegate的正确声明(iOS 12及以下) @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { ... }
- 完全关闭App(从后台划掉)
- 等待通知弹出,点击通知
- 看控制台是否打印出userInfo,同时你的业务逻辑是否触发
如果还是不行,可以检查一下通知权限是否正常授予,或者有没有其他地方覆盖了通知代理的设置。
内容的提问来源于stack exchange,提问作者Roberto Pinheiro

