Questo è un post ben usurato ... ma manca ancora una soluzione effettiva al problema (come sottolineato nei vari commenti).
La domanda originale riguarda il rilevamento di quando l'app è stata avviata
/ aperta da una notifica push, ad esempio un utente tocca la notifica. Nessuna delle risposte copre effettivamente questo caso.
Il motivo può essere visto nel flusso di chiamate quando arriva una notifica, application:didReceiveRemoteNotification...
viene chiamato quando viene ricevuta la notifica E di nuovo quando la notifica viene toccata dall'utente. Per questo UIApplicationState
motivo , non si può dire semplicemente guardando se l'utente lo ha toccato.
Inoltre, non è più necessario gestire la situazione di un "avvio a freddo" dell'app in application:didFinishLaunchingWithOptions...
quanto application:didReceiveRemoteNotification...
viene richiamata dopo il lancio in iOS 9+ (forse anche 8).
Quindi, come puoi sapere se l'utente tocca ha avviato la catena di eventi? La mia soluzione è contrassegnare l'ora in cui l'app inizia a uscire dallo sfondo o all'avvio a freddo e quindi a controllare tale orario application:didReceiveRemoteNotification...
. Se è inferiore a 0,1 s, allora puoi essere abbastanza sicuro che il tocco abbia attivato l'avvio.
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)
}
}
}
Ho provato questo per entrambi i casi (app in background, app non in esecuzione) su iOS 9+ e funziona come un fascino. 0.1s è anche abbastanza conservativo, il valore reale è ~ 0.002s quindi anche 0.01 va bene.