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

4
我知道这个主题已经有很多文章了,但我就是找不到正确的答案。
在iOS 8上是否有一种方法可以知道用户何时收到远程通知以及何时单击它。我想知道这个因为当我收到它时,我想保存它,当用户点击它时,我想打开一些视图。
我找到了这个答案https://dev59.com/8mQo5IYBdhLWcg3wBLYo#16393957,但问题是当用户在应用程序中并打开通知中心并单击其中一个时,应用程序既不处于非活动状态也不在后台。
我还发现了这个答案https://dev59.com/SGnWa4cB1Zd3GeqP3bdj#12937568,但我知道只有在应用程序被杀死并从新开始时才会运行。
我也不想这样做https://dev59.com/ClwY5IYBdhLWcg3w7rdX#32079458,因为我需要检测到我收到的通知。
有没有办法知道用户是否只是点击了通知?据我所知,这必须在didReceiveRemoteNotification中完成,但我不知道如何区分它们。而且我需要iOS 10之前的答案,因为应用程序的目标是iOS 8。
我的解决方案:
正如我在Shabbir Ahmad回答的评论中写的那样,我的解决方案是记住应用程序变为活动状态的日期和接收到通知的日期。如果这些日期之间的差异小于或等于一秒钟,我就认为用户点击了通知。
2个回答

3
你需要实现UNUserNotificationCenterDelegate及其方法userNotificationCenter(_:willPresent:withCompletionHandler:)userNotificationCenter(_:didReceive:withCompletionHandler:),当用户点击通知时会调用这些方法。在willPresent:中,你需要使用选项调用completionHandler,以指示应用程序在前台时接收到通知时应该发生什么。
注册这样的代理很容易:
UNUserNotificationCenter.current().delegate = self

所以举个例子:
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
    }
}

你可以通过AppDelegate实现该代理,但也可以通过任何NSObject来实现,我建议选择后者以保持AppDelegate尽可能干净整洁。
附注:当然,这假设你已经被用户授权(UNUserNotificationCenter.current().requestAuthorization(options:completionHandler:)),并且你已注册接受通知(UIApplication.shared.registerForRemoteNotifications())。
Scheduling and Handling Local Notifications中阅读更多内容,关于响应通知的发送 - 尽管此部分是关于本地通知的,但对于远程通知来说完全相同(它们都由同一个代理处理)。

我已经了解了UserNotifications,但据我所知,这只适用于iOS 10及以上版本,但我想知道是否有一种方法可以在iOS 10之前实现它。无论如何,还是谢谢。 - schmru

2

在 iOS 10 及之前的后台模式中,当您单击通知并处于前台时,两种情况下都会调用以下方法:

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

所以你可以区分行为,首先你需要在AppDelegate类中这样分配一个布尔类型的变量:

class AppDelegate: UIResponder, UIApplicationDelegate {

  var window: UIWindow?
  var isUserTapOnNotification = false

之后在代码中将 true 赋值给 isUserTapOnNotification

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

因为当您点击通知栏时,您的应用程序将进入前台,首先会调用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
}

}

之后,applicationDidBecomeActive会被调用,您需要像这样重置isUserTapOnNotificationfalse

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

我希望这个答案能够帮到你。


我只是想测试一些类似的解决方案,更多地是检查didbecomeactive和didreceivenotification之间的时间,如果在2秒(一些估计时间)以下,则表示这是一个点击。 - schmru

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接