简体   繁体   English

如何知道应用程序何时收到通知以及用户何时在iOS中点击通知

[英]How to know when app received notification and when user clicked on notification in iOS

I know there has been a lot written about this topic but I just can't find the right answer. 我知道有很多关于这个主题的文章,但我找不到正确的答案。

Is there a way how to know when the user received remote notification and when the user clicked on one on iOS 8. I would like to know this because when I receive it I want to save it and when user clicks on it I want to open some view. 有没有办法知道用户何时收到远程通知以及用户点击iOS 8上的一个。我想知道这一点,因为当我收到它时我想保存它,当用户点击它时我想打开一些观点。

I have found this answer https://stackoverflow.com/a/16393957/1241217 but the problem is when user is in the app and opens notification center and clicks on one, the app is not inactive and not in the background. 我找到了这个答案https://stackoverflow.com/a/16393957/1241217,但问题是当用户在应用程序中并打开通知中心并点击其中一个时,该应用程序不是非活动状态而不是在后台。

I also found this answer https://stackoverflow.com/a/12937568/1241217 but I know that this is ran only when the app is killed and started from new. 我也找到了这个答案https://stackoverflow.com/a/12937568/1241217,但我知道只有当应用程序被杀死并从新启动时才会运行。

I also don't want to do this https://stackoverflow.com/a/32079458/1241217 since I need to detect when I received notification. 我也不想这样做https://stackoverflow.com/a/32079458/1241217,因为我需要检测何时收到通知。

So is there a way how to know if the user only clicked on notification. 那么有一种方法可以知道用户是否只点击了通知。 As far as I understood it has to be done in didReceiveRemoteNotification but I don't know how to separate between them. 据我所知,它必须在didReceiveRemoteNotification中完成,但我不知道如何将它们分开。 And I need an answer for before iOS 10 because the app target is iOS 8. 我需要在iOS 10之前得到答案,因为应用目标是iOS 8。

MY SOLUTION: 我的解决方案

So as I wrote in the comment of Shabbir Ahmad answer my solution was to remember date when the application did become active and the date when the notification was received. 正如我在Shabbir Ahmad的评论中写道的那样,我的解决方案是记住应用程序确实生效的日期和收到通知的日期。 If the difference between this dates was a second or less I accepted that as the user clicked on the notification. 如果这个日期之间的差异是一秒或更短,我接受了当用户点击通知时。

You have to implement UNUserNotificationCenterDelegate and its method userNotificationCenter(_:willPresent:withCompletionHandler:) and userNotificationCenter(_:didReceive:withCompletionHandler:) which gets called when a user taps a notification. 您必须实现UNUserNotificationCenterDelegate及其方法userNotificationCenter(_:willPresent:withCompletionHandler:) userNotificationCenter(_:didReceive:withCompletionHandler:) userNotificationCenter(_:willPresent:withCompletionHandler:)userNotificationCenter(_:didReceive:withCompletionHandler:) ,当用户点击通知时会调用它。 In willPresent: you have to call the completionHandler with an option that would indicate what should happen when a notification arrives while the app is in foreground. willPresent:您必须使用一个选项调用completionHandler ,该选项将指示在应用程序处于前台时通知到达时应该发生的情况。

Registering such a delegate is easy: 注册这样的代表很容易:

UNUserNotificationCenter.current().delegate = self

So eg: 例如:

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    completionHandler(UNNotificationPresentationOptions.alert)
}

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    let userInfo = response.notification.request.content.userInfo
    if let userInfo = userInfo as? [String: Any] {
        // TODO: implement your logic
        // just don't forget to dispatch UI stuff on main thread
    }
}

You can implement that delegate by AppDelegate , but also by any NSObject , I would go with the latter to keep AppDelegate as clean as possible. 您可以通过AppDelegate实现该委托,也可以通过任何NSObject实现该委托,我会使用后者来保持AppDelegate尽可能干净。

PS: Of course, this assumes that you have been granted permissions by the user ( UNUserNotificationCenter.current().requestAuthorization(options:completionHandler:) ) and you are registered to accept notifications ( UIApplication.shared.registerForRemoteNotifications() ). PS:当然,这假设您已被用户授予权限( UNUserNotificationCenter.current().requestAuthorization(options:completionHandler:) )并且您已注册接受通知( UIApplication.shared.registerForRemoteNotifications() )。

Read more in Scheduling and Handling Local Notifications , section Responding to the Delivery of Notifications - while the section is about local notifications, it is exactly the same for the remote ones (they are handled both by the same delegate). 阅读更多调度和处理本地通知 ,请参阅响应通知传递部分 - 虽然该部分是关于本地通知的,但它与远程通知完全相同(它们由同一个代理处理)。

when you click on notification in background mode before ios 10 and when you are in foreground,in both cases your below method will call, 当您在ios 10之前以及在前台时在后台模式中单击通知时,在以下两种情况下,您的下方将调用,

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void)

So you can differentiate the behaviour, First of all you assign a boolean variable in AppDelegate class like this: 所以你可以区分行为,首先你在AppDelegate类中分配一个布尔变量,如下所示:

class AppDelegate: UIResponder, UIApplicationDelegate {

  var window: UIWindow?
  var isUserTapOnNotification = false

after that make true isUserTapOnNotification in 之后,使true isUserTapOnNotification

func applicationWillEnterForeground(_ application: UIApplication) {
        isUserTapOnNotification = tue
    }

because when you tap on notification bar, your app will came in foreground and applicationWillEnterForeground will call first, after that your didReceiveRemoteNotification will call: 因为当您点击通知栏时,您的应用程序将进入前台, applicationWillEnterForeground将首先调用,之后您的didReceiveRemoteNotification将调用:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

  if #available(iOS 10.0, *) {
//do nothing

}else { //<ios 10
 if isUserTapOnNotification == true {//when app is in background and user tap on notification bar
  //do action whatever you want
} else { //when user is in foreground and notification came,
  //before ios10,notification bar not display in foreground mode,So you can show popup by using userInfo
}

}

after that applicationDidBecomeActive will call and you reset isUserTapOnNotification to false like this: 在此之后, applicationDidBecomeActive将调用并将您的isUserTapOnNotification重置为false如下所示:

func applicationDidBecomeActive(_ application: UIApplication) {
       isUserTapOnNotification = false
    }

I hope this answer will help you. 我希望这个答案会对你有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 收到远程通知后,如何知道该应用程序当时是否处于活动状态? - When a remote notification is received, how to know whether the app is active at that time? 应用被杀死时是否收到 iOS 静默通知 - Is a iOS silent notification received when the app is killed 收到 iOS 推送通知时如何打开通知视图控制器? - How to Open a Notification view controller when a iOS push notification is received? 用户离开应用程序IOS时如何向用户发送本地通知 - How to send local notification to user when they leave the app IOS 应用程序处于前台时未收到推送通知 ios flutter - Push Notification not received when app is in foreground ios flutter 当应用程序收到通知时,IOS 向 HTTP 服务器发送请求 - IOS send request to HTTP server when app received notification 当应用程序在iOS 10中处于后台时,未收到推送通知 - Push notification not received when App is in Background in iOS 10 应用在前台运行时收到 iOS 推送通知 - iOS push notification received when app is running in foreground 在 iOS 上收到通知时确定应用程序是否在前台运行 - Determine if an app is running in the foreground when a notification is received on iOS iOS:当应用程序处于前台状态时,如何让用户忽略远程通知? - iOS: how to let the user ignore a remote notification when app is in foreground?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM