Esta é uma publicação bem usada ... mas ainda falta uma solução real para o problema (como é apontado nos vários comentários).
A pergunta original é sobre a detecção de quando o aplicativo foi iniciado
/ aberto a partir de uma notificação por push, por exemplo , um usuário toca na notificação. Nenhuma das respostas realmente cobre esse caso.
O motivo pode ser visto no fluxo de chamadas quando uma notificação chega, application:didReceiveRemoteNotification...
é chamado quando a notificação é recebida E novamente quando a notificação é tocada pelo usuário. Por causa disso, você não pode dizer apenas olhando se UIApplicationState
o usuário tocou nele.
Além disso, você não precisa mais lidar com a situação de 'partida a frio' do aplicativo, application:didFinishLaunchingWithOptions...
como application:didReceiveRemoteNotification...
é chamado novamente após o lançamento no iOS 9+ (talvez 8 também).
Então, como você pode saber se o usuário tocou na cadeia de eventos? Minha solução é marcar o horário em que o aplicativo começa a sair do segundo plano ou iniciar a frio e verificar o horário application:didReceiveRemoteNotification...
. Se for menor que 0,1s, você pode ter certeza de que o toque acionou a inicialização.
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)
}
}
}
Eu testei isso nos dois casos (aplicativo em segundo plano, aplicativo não em execução) no iOS 9 ou superior e funciona como um encanto. 0.1s também é bastante conservador, o valor real é ~ 0.002s, então 0.01 também é bom.