To bardzo wysłużony post ... ale wciąż brakuje w nim rzeczywistego rozwiązania problemu (jak wskazano w różnych komentarzach).
Pierwotne pytanie dotyczyło wykrycia, kiedy aplikacja została uruchomiona
/ otwarta z powiadomienia push, np. Użytkownik stuka w powiadomienie. Żadna z odpowiedzi tak naprawdę nie dotyczy tego przypadku.
Powód można zobaczyć w przebiegu połączenia, gdy nadejdzie powiadomienie, application:didReceiveRemoteNotification...
zostaje wywołany, gdy powiadomienie zostanie odebrane ORAZ ponownie, gdy powiadomienie zostanie dotknięte przez użytkownika. Z tego powodu nie można tego stwierdzić, patrząc po prostu, UIApplicationState
czy użytkownik ją stuknął.
Ponadto nie musisz już zajmować się sytuacją `` zimnego startu '' aplikacji, application:didFinishLaunchingWithOptions...
jak application:didReceiveRemoteNotification...
to się nazywa ponownie po uruchomieniu w iOS 9+ (może również 8).
Jak więc możesz stwierdzić, czy użytkownik kliknął, rozpoczął łańcuch zdarzeń? Moim rozwiązaniem jest zaznaczenie czasu, w którym aplikacja zaczyna wychodzić z tła lub zimnego startu, a następnie sprawdzenie tego czasu application:didReceiveRemoteNotification...
. Jeśli jest krótszy niż 0,1 s, możesz być całkiem pewien, że dotknięcie spowodowało uruchomienie.
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)
}
}
}
Szybki 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)
}
}
}
Przetestowałem to w obu przypadkach (aplikacja w tle, aplikacja nie działa) na iOS 9+ i działa jak urok. 0,1 s jest również dość konserwatywne, rzeczywista wartość to ~ 0,002 s, więc 0,01 również jest w porządku.