C'est un article bien usé ... mais il manque encore une solution réelle au problème (comme cela est souligné dans les différents commentaires).
La question initiale concerne la détection du moment où l'application a été lancée
/ ouverte à partir d'une notification push, par exemple un utilisateur appuie sur la notification. Aucune des réponses ne couvre réellement ce cas.
La raison peut être vue dans le flux d'appels lorsqu'une notification arrive, application:didReceiveRemoteNotification...
est appelé lorsque la notification est reçue ET à nouveau lorsque la notification est tapée par l'utilisateur. Pour cette raison, vous ne pouvez pas dire en regardant simplement UIApplicationState
si l'utilisateur l'a tapé.
De plus, vous n'avez plus besoin de gérer la situation d'un `` démarrage à froid '' de l'application application:didFinishLaunchingWithOptions...
comme application:didReceiveRemoteNotification...
on l'appelle à nouveau après le lancement dans iOS 9+ (peut-être aussi 8).
Alors, comment pouvez-vous savoir si l'utilisateur tap a commencé la chaîne d'événements? Ma solution consiste à marquer l'heure à laquelle l'application commence à sortir de l'arrière-plan ou à démarrer à froid, puis à enregistrer cette heure application:didReceiveRemoteNotification...
. S'il est inférieur à 0,1 s, vous pouvez être à peu près sûr que le robinet a déclenché le démarrage.
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)
}
}
}
J'ai testé cela pour les deux cas (application en arrière-plan, application non exécutée) sur iOS 9+ et cela fonctionne comme un charme. 0,1 s est également assez prudent, la valeur réelle est de ~ 0,002 s, donc 0,01 convient également.