Це добре зношений пост ... але все ще не вистачає фактичного рішення проблеми (на що вказується в різних коментарях).
Початкове запитання стосується виявлення, коли додаток було запущено
/ відкрито з натисненого повідомлення, наприклад, користувач натискає на сповіщення. Жодна з відповідей насправді не охоплює цю справу.
Причину можна побачити в потоці викликів, коли надходить повідомлення, application:didReceiveRemoteNotification...
отримує виклик, коли повідомлення отримано І знову, коли користувач натискає сповіщення. Через це ви не можете зрозуміти, просто подивившись на UIApplicationStateте, як користувач натиснув його.
Крім того, вам більше не потрібно обробляти ситуацію "холодного запуску" програми, application:didFinishLaunchingWithOptions...як application:didReceiveRemoteNotification...викликається знову після запуску в iOS 9+ (можливо, також 8).
Отже, як ви можете сказати, чи натиснути користувач запустив ланцюжок подій? Моє рішення - позначити час, коли програма починає виходити з фону або холодного початку, а потім перевірити цей час application:didReceiveRemoteNotification.... Якщо вона менше 0,1 с, то ви можете бути впевнені, що натискання спрацьовує при запуску.
Швидкий 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)
}
}
}
Швидкий 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)
}
}
}
Я перевірив це для обох випадків (додаток у фоновому режимі, програма не працює) на iOS 9+ і це працює як шарм. 0,1s теж досить консервативний, фактичне значення ~ 0,002s, тому 0,01 також добре.