Esta es una publicación muy desgastada ... pero todavía le falta una solución real al problema (como se señala en los diversos comentarios).
La pregunta original es acerca de detectar cuándo se inició
/ abrió la aplicación desde una notificación push, por ejemplo , un usuario toca la notificación. Ninguna de las respuestas cubre este caso.
La razón se puede ver en el flujo de llamadas cuando llega una notificación, application:didReceiveRemoteNotification...
recibe una llamada cuando se recibe la notificación Y nuevamente cuando el usuario toca la notificación. Debido a esto, no se puede saber con solo mirar UIApplicationState
si el usuario lo tocó.
Además, ya no necesita manejar la situación de un "arranque en frío" de la aplicación application:didFinishLaunchingWithOptions...
como application:didReceiveRemoteNotification...
se llama nuevamente después del lanzamiento en iOS 9+ (quizás 8 también).
Entonces, ¿cómo puede saber si el toque del usuario inició la cadena de eventos? Mi solución es marcar la hora a la que la aplicación comienza a salir del fondo o iniciar en frío y luego verificar esa hora application:didReceiveRemoteNotification...
. Si es inferior a 0.1s, puede estar seguro de que el toque activó el inicio.
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)
}
}
}
He probado esto para ambos casos (aplicación en segundo plano, aplicación no se ejecuta) en iOS 9+ y funciona de maravilla. 0.1s también es bastante conservador, el valor real es ~ 0.002s, por lo que 0.01 también está bien.