Đây là một bài viết mòn ... nhưng nó vẫn còn thiếu một giải pháp thực tế cho vấn đề (như được chỉ ra trong các ý kiến khác nhau).
Câu hỏi ban đầu là về việc phát hiện khi nào ứng dụng được khởi chạy
/ mở từ thông báo đẩy, ví dụ như người dùng nhấn vào thông báo. Không có câu trả lời thực sự bao gồm trường hợp này.
Lý do có thể được nhìn thấy trong luồng cuộc gọi khi có thông báo đến, application:didReceiveRemoteNotification...
được gọi khi nhận được thông báo VÀ lần nữa khi thông báo được gõ bởi người dùng. Bởi vì điều này, bạn không thể biết bằng cách chỉ nhìn vào UIApplicationState
thời tiết người dùng gõ nó.
Ngoài ra, bạn không còn cần phải xử lý tình huống 'khởi động nguội' của ứng dụng application:didFinishLaunchingWithOptions...
như application:didReceiveRemoteNotification...
được gọi lại sau khi khởi chạy trong iOS 9+ (có thể là 8).
Vì vậy, làm thế nào bạn có thể biết nếu người dùng nhấn bắt đầu chuỗi sự kiện? Giải pháp của tôi là đánh dấu thời gian ứng dụng bắt đầu ra khỏi nền hoặc bắt đầu lạnh và sau đó kiểm tra thời gian đó application:didReceiveRemoteNotification...
. Nếu nó nhỏ hơn 0,1, thì bạn có thể chắc chắn rằng vòi đã kích hoạt khởi động.
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)
}
}
}
Tôi đã thử nghiệm điều này cho cả hai trường hợp (ứng dụng ở chế độ nền, ứng dụng không chạy) trên iOS 9+ và nó hoạt động như một bùa mê. 0,1s cũng khá bảo thủ, giá trị thực tế là ~ 0,002s nên 0,01 cũng tốt.