iOS推送通知和AppDelegate方法的行为

11
我在StackOverflow和其他网站上进行了一些研究,试图弄清楚iOS推送通知如何影响AppDelegate生命周期方法以及哪个方法(不)被触发。研究的主要重点是“标准”iOS推送通知(带有“alert”字段)和静默推送通知(只设置“content-available”为1),以及AppDelegate的application:didReceiveRemoteNotification和application:didFinishLaunchingWithOptions方法。
我不想针对不同情况提出很多问题,而是尝试写下我尝试过的不同测试用例的陈述,并在此之后向您询问:
是否有任何错误的声明?如果有,哪一个,为什么?
场景1:应用程序已使用并通过点击主页按钮放置在后台。
1. 如果发送标准推送通知,在推送通知到达时,没有任何方法会被触发,应用程序保持不活跃。一旦推送通知被点击并因此打开了应用程序,application:didReceiveRemoteNotification方法将被调用,application:didFinishLaunchingWithOptions不会被调用。我在将应用程序放置在后台后立即测试了这种情况,也在应用程序背景中超过一小时后测试了它-相同的行为。我想,如果由于某种原因iOS在后台运行时杀死了我的应用程序,那么这个测试用例将变成下面的场景2,陈述1,对吗?
2. 如果发送静默推送通知,在推送通知到达时,application:didReceiveRemoteNotification方法将被调用,application:didFinishLaunchingWithOptions不会被调用。
场景2:应用程序已使用并通过从正在运行的应用程序列表中滑动它来关闭。
1. 如果发送标准推送通知,在推送通知到达时,没有任何方法被触发,应用程序保持关闭状态。一旦推送通知被点击并因此打开了应用程序,application:didReceiveRemoteNotification方法将被调用,application:didFinishLaunchingWithOptions不会被调用。
2. 如果发送静默推送通知,则不会触发任何方法,因为静默推送通知无法发送到已关闭的应用程序。在通知发送后打开应用程序时,application:didFinishLaunchingWithOptions作为正常流程的一部分被调用,而没有任何推送通知信息。application:didReceiveRemoteNotification不会被调用。
如果您可以想到其他我可能忘记提及的真实情况,我会非常感激了解它们以及在这些情况下会发生什么。
干杯
更新#1
感谢Sandeep Bhandari提供的更新和额外的场景。我原始问题中忘记提到了一种情况,即应用程序出于任何原因当前不在前台的情况下,我正在探索的场景。
将Sandeep的场景添加到列表中:
场景3:正在使用应用程序并收到推送通知。
如果发送标准推送通知,将调用“application:didReceiveRemoteNotification”方法。不会调用“application:didFinishLaunchingWithOptions”。
如果发送静默推送通知,将调用“application:didReceiveRemoteNotification”方法。不会调用“application:didFinishLaunchingWithOptions”。
场景4:应用程序在后台运行。
如果发送标准推送通知,将调用“application:didReceiveRemoteNotification”方法。不会调用“application:didFinishLaunchingWithOptions”。
如果发送静默推送通知,将调用“application:didReceiveRemoteNotification”方法。不会调用“application:didFinishLaunchingWithOptions”。

1
我想提一个小意见...你说“通过从正在运行的应用程序列表中滑动来终止它”,这并不完全准确。该列表并不仅显示正在运行的应用程序。它是最近使用过的应用程序列表。即使应用程序已经被终止,它们仍然可以出现在此列表中。 - Bradley Thomas
2个回答

14

通过经验和对iOS推送通知的深入研究,无论应用程序处于前台还是后台,都会触发相同的委托方法,即didReceiveRemoteNotification

静默推送通知具有不同的处理程序:(content-available为1表示为静默通知)

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

    }

当应用程序已经停止运行时,对于常规推送通知,didReceiveRemoteNotification 永远不会被调用。必须在 didFinishLaunchingWithOptions 中进行处理,如下所示:

当应用程序停止运行时,常规推送通知将无法触发 didReceiveRemoteNotification 方法。因此,需要在 didFinishLaunchingWithOptions 方法中进行相应的处理,代码如下:

// handle notification when app is closed.
let notification = launchOptions?[.remoteNotification]
if notification != nil {
    self.application(application, didReceiveRemoteNotification: notification as! [AnyHashable : Any])
}

附加信息:

测试在应用程序被杀死时接收推送通知的方法是,从双击主页按钮时出现的列表中删除?

查看日志和进行调试的正确方法是通过编辑运行方案并选择等待可执行文件启动

输入图像描述

从Xcode中运行应用程序。然后从服务器发送推送通知,然后从通知中心点击通知。


1
谢谢回复!当应用程序被杀死时发送推送通知,我在两种不同的情况下进行了测试。1)我已经在生产中的应用程序中进行了测试,如果触发其中一些方法,则应该以不同的方式触发后端服务器,并简单地杀死应用程序并向我的设备发送推送通知。2)我已按照您在此屏幕截图中描述的确切方式测试了应用程序的调试版本:我已经安装了应用程序,用滑动杀死它,然后我从Xcode运行并等待可执行文件启动时发送通知。 - uerceg
@hasan83 先生,但对我没有用。我的意思是,如果我点击应用程序图标,launchOptions?[.remoteNotification] 将不起作用,因为 launchOptions 将为 nil。您的答案仅在通过通知中心上的通知打开应用程序时有效。是否有任何方法可以处理这种情况:当应用程序终止,我收到通知并点击应用程序图标而不是点击通知? - rafaelbpa
所以你是说当收到通知时,你会通过点击应用程序图标自己打开应用程序吗? - hasan
@rafaelbpa 这不是 iOS 的行为方式。手动打开应用程序将无法让您访问通知。这是不可能的。应用程序从未知道它。唯一的方法是通过调用 API 来检查是否有任何通知。但这不是通常应用的用户体验! - hasan

1

我认为你的陈述没有问题,但是我认为你错过了另外两种情况需要迭代。

  1. 应用在前台并接收到推送通知:当APNS传递到iOS时,didReceiveRemoteNotification会立即被调用,您可以通过检查didRecieveRemoteNotification方法中的应用程序状态来处理它。

  2. 应用程序在后台运行:我相信您已经了解了iOS的后台模式。如果应用程序使用过期处理程序,则即使通过点击主屏幕按钮将其置于后台,应用程序仍将保持活动状态。应用程序在后台运行的持续时间取决于各种因素(一些教程说应用程序保持活动状态3分钟,但我无法保证)。即使在这种情况下,didReceiveRemoteNotification也会在APNS传递到iOS时立即被调用。只是此时应用程序不会在前台,但仍然处于活动状态!


1
啊,是的。抱歉,我实际上忘了提到我的重点是关于在应用程序不在前台时传递通知。我会在我的问题中更新这一点。感谢您提供的第二种情况,我忘记了它。我也会将其添加到我的问题中,以便更好地概述我们已经详细讨论过哪些情况。非常感谢您的答复! - uerceg

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