通过推送通知检测应用程序是否已经启动/打开

是否可以通过推送通知知道应用程序是否已经启动/打开?

我想发射活动可以在这里看到:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {


if (launchOptions != nil) {
// Launched from push notification
NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];


}
}

但是,当应用程序处于后台时,如何从推送通知中检测它是否被打开?

146323 次浏览

你可使用:

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo

来处理远程推送通知。

检查这里的 文件

是的,你可以在 应用代表中用这种方法检测:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
/* your Code*/
}

本地通知:

- (void)application:(UIApplication *)application
didReceiveLocalNotification:(UILocalNotification *)notification
{
/* your Code*/
}

请看这段代码:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
if ( application.applicationState == UIApplicationStateInactive || application.applicationState == UIApplicationStateBackground  )
{
//opened from a push notification when the app was on background
}
}

和你一样

-(void)application:(UIApplication *)application didReceiveLocalNotification (UILocalNotification *)notification

直接从文件上看到的

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo:nil

如果应用程序正在运行并接收到远程通知,则应用程序调用此方法来处理通知。

此方法的实现应该使用通知来采取适当的操作。

过一会儿

如果当推送通知到达时应用程序没有运行,该方法将启动应用程序并在启动选项字典中提供适当的信息。

应用程序不调用此方法来处理推送通知。

相反,您的

application:willFinishLaunchingWithOptions:

或者

application:didFinishLaunchingWithOptions:

方法需要获取推送通知有效负载数据并作出适当的响应。

application:didReceiveRemoteNotification:检查你是否收到通知时,你的应用程序在前台或后台。

如果它是在后台接收的,则从通知中启动应用程序。

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
NSLog(@"Notification received by running app");
} else {
NSLog(@"App opened from Notification");
}
}

迟到了,但也许有用

当应用程序不运行时

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

叫做。

哪里需要检查推送通知

NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (notification) {
NSLog(@"app recieved notification from remote%@",notification);
[self application:application didReceiveRemoteNotification:notification];
} else {
NSLog(@"app did not recieve notification");
}

快速:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
PFPush.handlePush(userInfo)


if application.applicationState == UIApplicationState.Inactive || application.applicationState == UIApplicationState.Background {
//opened from a push notification when the app was in the background


}


}

我还没有试过,但也许你可以给自己发一个通知

对于 swift

 func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]){


++notificationNumber
application.applicationIconBadgeNumber =  notificationNumber;


if let aps = userInfo["aps"] as? NSDictionary {


var message = aps["alert"]
println("my messages : \(message)")


}
}

对于迅捷用户:

如果你想打开一个不同的页面从推或类似的东西,你需要检查它在 didFinishLaunchingWithOptions像:

let directVc: directVC! = directVC(nibName:"directVC", bundle: nil)
let pushVc: pushVC! = pushVC(nibName:"pushVC", bundle: nil)


if let remoteNotification = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? NSDictionary {
self.navigationController = UINavigationController(rootViewController: pushVc!)
} else {
self.navigationController = UINavigationController(rootViewController: directVc!)
}
self.window!.rootViewController = self.navigationController

Swift 2.0“未运行”状态(本地和远程通知)

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {




// Handle notification
if (launchOptions != nil) {


// For local Notification
if let localNotificationInfo = launchOptions?[UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification {


if let something = localNotificationInfo.userInfo!["yourKey"] as? String {
self.window!.rootViewController = UINavigationController(rootViewController: YourController(yourMember: something))
}




} else


// For remote Notification
if let remoteNotification = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as! [NSObject : AnyObject]? {


if let something = remoteNotification["yourKey"] as? String {
self.window!.rootViewController = UINavigationController(rootViewController: YourController(yourMember: something))
}
}


}




return true
}
     // shanegao's code in Swift 2.0
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject])
{
if ( application.applicationState == UIApplicationState.Inactive || application.applicationState == UIApplicationState.Background ){
print("opened from a push notification when the app was on background")
}else{
print("opened from a push notification when the app was on foreground")
}
}

当应用程序终止时,用户点击推送通知

public func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] != nil {
print("from push")
}
}

当应用程序在后台,用户点击推送通知

如果用户从系统显示的警报中打开应用程序,系统可能会再次调用此方法 当你的应用程序即将进入前台,以便您可以更新用户界面并显示与通知相关的信息。

public func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
if application.applicationState == .inactive {
print("from push")
}
}

取决于你的应用程序,它也可以发送与 aps内的 content-available无声推,所以也要注意这一点:)见 https://stackoverflow.com/a/33778990/1418457

这是一个老掉牙的帖子... ... 但它仍然缺少一个实际的 解决方案来解决这个问题(正如在各种评论中指出的那样)。

最初的问题是关于检测应用程序是何时启动的 /打开了发出推送通知,例如:。用户点击 所有的答案都不包括这个案子。

原因可以在通知到达时的呼叫流程中看到,即 application:didReceiveRemoteNotification...

当用户点击通知时,再次接收到 还有通知时调用。正因为如此,您不能仅仅通过查看 UIApplicationState来判断用户是否点击了它。

此外,你不再需要在 application:didFinishLaunchingWithOptions...中处理应用程序的“冷启动”情况,因为在 iOS9 + 中启动后 application:didReceiveRemoteNotification...会再次被调用(也许也是8)。

那么,如何判断用户点击是否启动了事件链呢?我的解决方案是标记应用程序开始从后台出来或冷启动的时间,然后在 application:didReceiveRemoteNotification...中检查该时间。如果它小于0.1秒,那么您可以非常肯定的点击触发了启动。

Swift 2. x

class AppDelegate: UIResponder, UIApplicationDelegate {


var wakeTime : NSDate = NSDate()        // when did our application wake up most recently?


func applicationWillEnterForeground(application: UIApplication) {
// time stamp the entering of foreground so we can tell how we got here
wakeTime = NSDate()
}


func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// ensure the userInfo dictionary has the data you expect
if let type = userInfo["type"] as? String where type == "status" {
// IF the wakeTime is less than 1/10 of a second, then we got here by tapping a notification
if application.applicationState != UIApplicationState.Background && NSDate().timeIntervalSinceDate(wakeTime) < 0.1 {
// User Tap on notification Started the App
}
else {
// DO stuff here if you ONLY want it to happen when the push arrives
}
completionHandler(.NewData)
}
else {
completionHandler(.NoData)
}
}
}

Swift 3

class AppDelegate: UIResponder, UIApplicationDelegate {


var wakeTime : Date = Date()        // when did our application wake up most recently?


func applicationWillEnterForeground(_ application: UIApplication) {
// time stamp the entering of foreground so we can tell how we got here
wakeTime = Date()
}


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


// ensure the userInfo dictionary has the data you expect
if let type = userInfo["type"] as? String, type == "status" {
// IF the wakeTime is less than 1/10 of a second, then we got here by tapping a notification
if application.applicationState != UIApplicationState.background && Date().timeIntervalSince(wakeTime) < 0.1 {
// User Tap on notification Started the App
}
else {
// DO stuff here if you ONLY want it to happen when the push arrives
}
completionHandler(.newData)
}
else {
completionHandler(.noData)
}
}
}

我已经在 iOS9 + 上测试了这两种情况(后台应用程序,应用程序不运行) ,它的工作原理非常棒。0.1 s 也相当保守,实际值大约是0.002 s,所以0.01也不错。

斯威夫特:

我正在运行推送通知(带有背景提取)。当我的应用程序处于后台并且我收到一个推送通知时,我发现将会调用 appCommittee 中的 did ReceiveRemoteNotification 两次; 一次是在收到通知时调用,另一次是在用户单击通知警报时调用。

要检测是否单击了通知警报,只需检查 appDelegate 中 did ReceiveRemoteNotification 内的 applicationState raw value = = 1。

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject: AnyObject]) {
// If not from alert click applicationState(1)
if (application.applicationState.rawValue != 1) {
// Run your code here
}
}

希望这个能帮上忙。

如果有人想要迅捷3的答案

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
switch application.applicationState {
case .active:
//app is currently active, can update badges count here
break
case .inactive:
//app is transitioning from background to foreground (user taps notification), do what you need when user taps here
break
case .background:
//app is in background, if content-available key of your notification is set to 1, poll to your backend to retrieve data and update your interface here
break
default:
break
}
}

我们遇到的问题是在应用程序启动后正确更新视图。这里有一些复杂的生命周期方法序列,令人困惑。

生命周期方法

我们对 iOS 10的测试揭示了以下不同情况下的生命周期方法序列:

DELEGATE METHODS CALLED WHEN OPENING APP


Opening app when system killed or user killed
didFinishLaunchingWithOptions
applicationDidBecomeActive


Opening app when backgrounded
applicationWillEnterForeground
applicationDidBecomeActive


DELEGATE METHODS CALLED WHEN OPENING PUSH


Opening push when system killed
[receiving push causes didFinishLaunchingWithOptions (with options) and didReceiveRemoteNotification:background]
applicationWillEnterForeground
didReceiveRemoteNotification:inactive
applicationDidBecomeActive


Opening push when user killed
didFinishLaunchingWithOptions (with options)
didReceiveRemoteNotification:inactive [only completionHandler version]
applicationDidBecomeActive


Opening push when backgrounded
[receiving push causes didReceiveRemoteNotification:background]
applicationWillEnterForeground
didReceiveRemoteNotification:inactive
applicationDidBecomeActive

问题是

好了,现在我们需要:

  1. 确定用户是否正在通过推送打开应用程序
  2. 根据推送状态更新视图
  3. 清除状态,以便后续打开时不会将用户返回到相同的位置。

棘手的地方在于,更新视图必须在应用程序实际处于活动状态时进行,这在所有情况下都是相同的生命周期方法。

我们解决方案的草图

以下是我们解决方案的主要组成部分:

  1. 在“应用委托”上存储一个 notificationUserInfo实例变量。
  2. applicationWillEnterForegrounddidFinishLaunchingWithOptions中设置 notificationUserInfo = nil
  3. didReceiveRemoteNotification:inactive中设置 notificationUserInfo = userInfo
  4. applicationDidBecomeActive始终调用自定义方法 openViewFromNotification并传递 self.notificationUserInfo。如果 self.notificationUserInfo为空,则提前返回,否则根据 self.notificationUserInfo中的通知状态打开视图。

解释

当从推入式 didFinishLaunchingWithOptionsapplicationWillEnterForeground打开时,总是在 didReceiveRemoteNotification:inactive之前立即调用,所以我们首先在这些方法中重置 notificationUserInfo,这样就不会出现过时状态。然后,如果 didReceiveRemoteNotification:inactive被调用,我们知道我们正在从一个推开,所以我们设置 self.notificationUserInfo,然后由 applicationDidBecomeActive提取用户转发到正确的视图。

最后一种情况是,如果用户在应用程序切换器中打开了应用程序(即在应用程序在前台时双击 home 按钮) ,然后接收到一个推送通知。在这种情况下,只调用了 didReceiveRemoteNotification:inactive,而 WillEnterForeground 和 FinishLaunching 都没有被调用,因此需要一些特殊的状态来处理这种情况。

希望这个能帮上忙。

这个问题的问题在于“打开”这个应用程序没有明确的定义。一个应用程序要么是从非运行状态冷启动,要么是从非活动状态重新激活(例如从另一个应用程序切换回来)。下面是我区分所有这些可能状态的解决方案:

typedef NS_ENUM(NSInteger, MXAppState) {
MXAppStateActive = 0,
MXAppStateReactivated = 1,
MXAppStateLaunched = 2
};


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// ... your custom launch stuff
[[MXDefaults instance] setDateOfLastLaunch:[NSDate date]];
// ... more custom launch stuff
}


- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// Through a lot of trial and error (by showing alerts), I can confirm that on iOS 10
// this method is only called when the app has been launched from a push notification
// or when the app is already in the Active state.  When you receive a push
// and then launch the app from the icon or apps view, this method is _not_ called.
// So with 99% confidence, it means this method is called in one of the 3 mutually exclusive cases
//    1) we are active in the foreground, no action was taken by the user
//    2) we were 'launched' from an inactive state (so we may already be in the main section) by a tap
//       on a push notification
//    3) we were truly launched from a not running state by a tap on a push notification
// Beware that cases (2) and (3) may both show UIApplicationStateInactive and cant be easily distinguished.
// We check the last launch date to distinguish (2) and (3).


MXAppState appState = [self mxAppStateFromApplicationState:[application applicationState]];
//... your app's logic
}


- (MXAppState)mxAppStateFromApplicationState:(UIApplicationState)state {
if (state == UIApplicationStateActive) {
return MXAppStateActive;
} else {
NSDate* lastLaunchDate = [[MXDefaults instance] dateOfLastLaunch];
if (lastLaunchDate && [[NSDate date] timeIntervalSinceDate:lastLaunchDate] < 0.5f) {
return MXAppStateLaunched;
} else {
return MXAppStateReactivated;
}
}
return MXAppStateActive;
}

MXDefaults只是 NSUserDefaults的一个小包装。

我将从一个状态图开始,这个状态图是我自己创建的,用来更准确地将其可视化,并考虑所有其他状态: Https://docs.google.com/spreadsheets/d/e/2pacx-1vsdkogo_f1tzwgjbaed4c_7cml0beatqel3p9ukpbwaslt6zku3ildznozoevkmzoeng7gs31ifhd-l/pubhtml?gid=0&single=true

使用这个图表,我们可以看到为了开发一个可以在几乎所有可能的用例中工作的健壮的通知处理系统实际上需要什么。

完整的溶液

  • Did ReceiveRemoteNotification中存储 通知有效载荷
  • 应用程序 WillEnterForeground中清除 存储通知,并且 < strong > did FinishLaunchingWithOptions
  • 为了处理控制中心/通知中心拖动的情况,您可以使用一个标志 Will ResignActiveCall,并在初始时将其设置为 假的, 在 返回文章页面应用程序 WillResignActive 译者:方法中将其设置为 没错,
  • Did ReceiveRemoteNotification方法中,只有当 willResignActiveCalled 为 false 时才保存通知(userInfo)。
  • 后台应用程序 DidBecomeActive方法中重置 被调用为 false

注意: 类似的答案建议在评论 Eric 的答案,但是,状态表有助于找到所有可能的场景,就像我在我的应用程序中做的那样。

请查找下面的完整代码,如果没有处理任何具体案件,请在下面发表评论:

应用代理

class AppDelegate: UIResponder, UIApplicationDelegate {
private var willResignActiveCalled = false


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
NotificationUtils.shared.notification = nil
return true
}
func applicationWillResignActive(_ application: UIApplication) {
willResignActiveCalled = true
}
func applicationDidEnterBackground(_ application: UIApplication) {
willResignActiveCalled = false
}
func applicationWillEnterForeground(_ application: UIApplication) {
NotificationUtils.shared.notification = nil
}
func applicationDidBecomeActive(_ application: UIApplication) {
willResignActiveCalled = false
NotificationUtils.shared.performActionOnNotification()
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
if !willResignActiveCalled { // Check if app is in inactive by app switcher, control center, or notification center
NotificationUtils.shared.handleNotification(userInfo: userInfo)
}
}
}

NotificationUtils : 在这里,你可以编写所有的代码来导航到应用程序的不同部分,处理数据库(CoreData/Domain) ,以及在收到通知时做所有其他需要做的事情。

   class NotificationUtils {
static let shared = NotificationUtils()
private init() {}


var notification : [AnyHashable: Any]?


func handleNotification(userInfo : [AnyHashable: Any]){
if UIApplication.shared.applicationState == UIApplicationState.active {
self.notification = userInfo //Save Payload
//Show inApp Alert/Banner/Action etc
// perform immediate action on notification
}
else if UIApplication.shared.applicationState == UIApplicationState.inactive{
self.notification = userInfo
}
else if UIApplication.shared.applicationState == UIApplicationState.background{
//Process notification in background,
// Update badges, save some data received from notification payload in Databases (CoreData/Realm)
}
}


func performActionOnNotification(){
// Do all the stuffs like navigating to ViewControllers, updating Badges etc
defer {
notification = nil
}
}
}

当应用程序在后台作为 Shanegao你可以使用

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
if ( application.applicationState == UIApplicationStateInactive || application.applicationState == UIApplicationStateBackground  )
{
//opened from a push notification when the app was on background
}
}

但是,如果你想启动应用程序,当应用程序关闭,你想调试你的应用程序,你可以到 编辑计划和在左侧菜单选择 快跑,然后在启动选择 等待启动可执行文件,然后你应用程序启动时,你点击推送通知

编辑方案 > 运行 > 等待可执行文件启动

为 Xamarin 用户发布此文。

检测应用程序是否通过推送通知启动的关键是 AppDelegate.FinishedLaunching(UIApplication app, NSDictionary options)方法和传入的选项字典。

如果是本地通知,选项字典中将包含这个键: UIApplication.LaunchOptionsLocalNotificationKey

如果是远程通知,则为 UIApplication.LaunchOptionsRemoteNotificationKey

当键为 LaunchOptionsLocalNotificationKey时,对象的类型为 UILocalNotification。 然后您可以查看通知并确定它是哪个特定的通知。

提示: UILocalNotification没有标识符,就像 UNNotificationRequest一样。在包含 requestId 的 UserInfo 中放入一个字典键,这样在测试 UILocalNotification时,您就可以使用一个特定的 requestId 作为逻辑的基础。

我发现,即使在 iOS 10 + 设备上,当使用 UNUserNotificationCenterAddNotificationRequestUNMutableNotificationContent创建位置通知时,当应用程序不运行时(我关闭了它) ,通过点击通知中心的通知启动时,字典仍然包含 UILocalNotificaiton对象。

这意味着我检查基于通知启动的代码将在 iOS8和 iOS10 + 设备上工作

public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
_logger.InfoFormat("FinishedLaunching");


if(options != null)
{
if (options.ContainsKey(UIApplication.LaunchOptionsLocalNotificationKey))
{
//was started by tapping a local notification when app wasn't previously running.
//works if using UNUserNotificationCenter.Current.AddNotificationRequest OR UIApplication.SharedApplication.PresentLocalNotificationNow);


var localNotification = options[UIApplication.LaunchOptionsLocalNotificationKey] as UILocalNotification;


//I would recommended a key such as this :
var requestId = localNotification.UserInfo["RequestId"].ToString();
}
}
return true;
}
func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any]) {
print("Push notification received: \(data)")


if let info = data["aps"] as? Dictionary<String, AnyObject> {
let alertMsg = info["alert"] as! String
print(alertMsg)
switch application.applicationState {
case .active:
print("do stuff in case App is active")
case .background:
print("do stuff in case App is in background")
// navigateToChatDetailViewControler(pushdata: data)
case .inactive:
print("do stuff in case App is inactive")
// navigateToChatDetailViewControler(pushdata: data)
}
}
}

只有一种可靠的方法,而且只适用于 IOS 10 + :

使用 UNUserNotificationCenter实现 UNUserNotificationCenterDelegate方法:

- (void) userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {


//Here you can get your original push if you need to
NSDictionary* pusDict = response.notification.request.content.userInfo;


if ([response.actionIdentifier isEqualToString: UNNotificationDefaultActionIdentifier]) {
//User tapped the notification
} else if ([response.actionIdentifier isEqualToString: UNNotificationDismissActionIdentifier]) {
//User dismissed the notification
} else if ([response.actionIdentifier isEqualToString: MYCustomActionId]) {
//User chose my custom defined action
}
...
}

Xcode 10 Swift 4.2

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {


let state : UIApplicationState = application.applicationState
if (state == .Inactive || state == .Background) {
// coming from background
} else {
// App is running in foreground
}
}

M.Othman 的答案对于不包含 < strong > Scene 委托的应用程序是正确的 对于 场景委托应用程序来说,这在 iOS 13上对我很有用

下面是应该用 会连接现场编写的代码

if connectionOptions.notificationResponse == nil {
//Not opened from push notification
} else {
//Opened from push notification
}

应用程序委托支持早期版本的代码 完成启动选项

let notification = launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification]
if (notification != nil) {


//Launched from push notification
} else {


//Launch from other source
}

如果您运行的是 IOS13或以上,请在 场景代表:中使用此代码

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    

guard let notificationResponse = connectionOptions.notificationResponse else { return }
    

let pushTitle = notificationResponse.notification.request.content.title
let pushSubtitle = notificationResponse.notification.request.content.subtitle
let pushBody = notificationResponse.notification.request.content.body
    

// do your staff here
}

M.Othman 对 Swift 5的回答(尽管使用 NSLog 是 不再推荐了)

在设置显示 RootViewController所需的所有内容之后添加以下内容。在 application(_:didReceiveRemoteNotification)中,您应该添加能够区分第一次启动和后台启动类型的逻辑。

if let launchOptions = launchOptions,
let notification = launchOptions[UIApplicationLaunchOptionsKey.remoteNotification]
as? [AnyHashable : Any] {
NSLog("app recieved notification from remote \(notification)")
self.application(application, didReceiveRemoteNotification: notification)
} else {
NSLog("app did not recieve notification")
}

斯威夫特针对这个问题的其他一些具体答案可以在 如何处理启动选项在 Swift 3时,通知被点击? 得到语法问题找到

2021,Swift 5,本地通知仅 :

UNUserNotificationCenter.current().delegate = self


extension YourClass: UNUserNotificationCenterDelegate {


func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let notificationIdentifier = response.notification.request.identifier


// If this is called, then your app was opened from a local notification with this identifier
}
}




如果你的应用程序中有 SceneDelegate,那么你应该使用下面的代码来管理 本地/远程通知,当你的应用程序被杀死/终止,你打开应用程序从点击通知

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    

//Handle Notification Response
guard let notifiResponse = connectionOptions.notificationResponse else { return }
    

if notifiResponse.notification.request.trigger is UNTimeIntervalNotificationTrigger { //Local Notification
Messaging.messaging().appDidReceiveMessage(notifiResponse.notification.request.content.userInfo)
        

print("Receive Local Notifications")
}
else if notifiResponse.notification.request.trigger is UNPushNotificationTrigger{ //Remote Notification
        

print("Receive Remote Notifications")
}
}

当应用程序处于后台/前台状态时,使用 AppDelegate管理本地/远程通知。

extension AppDelegate : UNUserNotificationCenterDelegate {


func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
                   

if response.notification.request.trigger is UNTimeIntervalNotificationTrigger{
print("Receive Local Notifications")
}
else if response.notification.request.trigger is UNPushNotificationTrigger{
print("Receive Remote Notifications")
}
    

let userInfo = response.notification.request.content.userInfo
completionHandler()
}


func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
print("willPresent Notifications")


if notification.request.trigger is UNTimeIntervalNotificationTrigger{
print("Receive Local Notifications")
}
else {
print("Receive Remote Notifications")
}
completionHandler([.banner, .list, .sound])
}
}