Handle tap on local notification when app is terminated - iOS - Swift
When you tap on Push Notification on Notification Center.
OS launches your app (terminated before) then STILL delivers the action to this (Function 1)
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
)
You can get the notification
object from response like what you did.
But you may need to save temporary this data from the selected push notification, then handle it later when app is completely active with user.
Remember to call completionHandler()
when you finish your logic. And, you must set UNUserNotificationCenter.current().delegate = self
, before you return true
in
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool`.
self
here is your AppDelegate
, which means you set UserNotification's delegate to a live object or initialized object.
It will be able to handle the above delegate function call (Function 1) to get your selected push notification's data.
How to handle push notification when app is not running/app is terminated
If the app is not running (killed state) , you can't execute any methods or code , only if the user clicks the push notification you can receive object of it in didFinishLaunchingWithOptions
launchingOptions and handle it ....
How to call API when app is terminated in push notifcation iOS Swift?
As per Apple guidelines, you can get push notification for the background as well as on foreground state but when it comes to
Terminate state apple don't allow you to automatically open the app or
do any kind of operation unless you launch the app through notification.
Though you can handle notification during the Terminated state using Launch Options at the time of app launch.
Coding Example:
In your AppDelegate.swift import firebase library
import Firebase
import FirebaseInstanceID
import FirebaseMessaging
import UserNotifications
Whenever app launch register for push notification service, add the following lines of code into your didFinishLaunchingWithOptions
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
registerForPushNotifications(application: application)
handleNotificationWhenAppIsKilled(launchOptions)
return true
}
func handleNotificationWhenAppIsKilled(_ launchOptions: [UIApplicationLaunchOptionsKey: Any]?) {
// Check if launched from the remote notification and application is close
if let remoteNotification = launchOptions?[.remoteNotification] as? [AnyHashable : Any] {
// Handle your app navigation accordingly and update the webservice as per information on the app.
}
}
Add extension methods of appDelegate to register for remote notification and to get device token from APNS
//MARK: - Notifications related...
extension AppDelegate {
func registerForPushNotifications(application: UIApplication) {
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
// For iOS 10 data message (sent via FCM
Messaging.messaging().delegate = self
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
let savedAPNSToken = UserDefaults.standard.object(forKey: "savedAPNSToken") as? String
if savedAPNSToken != token {
UserDefaults.standard.set(token, forKey: "savedAPNSToken")
UserDefaults.standard.synchronize()
Messaging.messaging().apnsToken = deviceToken
}
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print(error.localizedDescription)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
completionHandler(UIBackgroundFetchResult.newData)
}
}
Use the following methods of notificationCenter to handle notification in the foreground and background states :
// MARK: - UNUserNotificationCenterDelegate
@available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
// Receive displayed notifications for iOS 10 devices.
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
completionHandler([.alert])
}
/// Handle tap on the notification banner
///
/// - Parameters:
/// - center: Notification Center
/// - response: Notification response
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
completionHandler()
}
Firebase token renewel:
extension AppDelegate : MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
// Note: This callback is fired at each app startup and whenever a new token is generated.
let savedFCMToken = UserDefaults.standard.object(forKey: "savedFCMToken") as? String
if savedFCMToken != fcmToken {
UserDefaults.standard.set(fcmToken, forKey: "savedFCMToken")
UserDefaults.standard.synchronize()
// Update FCMToken to server by doing API call...
}
}
}
Handling Push Notifications when App is Terminated
As per your question, there is no way to hold all the notification when you open the app, better you call an api to get all notification as per time stamp from your back end/server that's how Facebook does.
Handle Notifications when app is terminated(iOS)
Have you tried using getDeliveredNotifications(completionHandler:)
? You can call the following code in e.g. the viewDidLoad method of the controller in which you display the received notifications.
Note that if the user clears the received notifications in the notification center this won't work. You'll have to do as mentioned in the accepted answer of the question you linked in your comment.
UNUserNotificationCenter.current().getDeliveredNotifications { notifications in
// notifications: An array of UNNotification objects representing the local
// and remote notifications of your app that have been delivered and are still
// visible in Notification Center. If none of your app’s notifications are
// visible in Notification Center, the array is empty.
// As said in the documentation, this closure may be executed in a background
// thread, so if you want to update your UI you'll need to do the following:
DispatchQueue.main.sync { /* or .async {} */
// update UI
}
}
Firebase push notifications callback doesn't work when app is terminated
I resolved this by using the .getInitialMessage()
function (This is the callback if the app is terminated.
My notifications worked when the app was on background but not terminated.
To resolve this I just added this to my code:
FirebaseMessaging.instance
.getInitialMessage()
.then((RemoteMessage message) {
if (message != null) {
Navigator.pushNamed(context, message.data['view']);
}
});
I've made a working demo here
Related Topics
Uitableview Inside Uiscrollview Not Receiving First Tap After Scrollling
How to Debug an iOS Extension (.Appex)
App Not Sized Properly iOS 8 iPhone Simulator
How to Attach Debugger to iOS App After Launch
Ios4: How to Use Video File as an Opengl Texture
How to Add Strings on X Axis in iOS-Charts
Button in Uitableviewcell Not Responding Under iOS 7
Urlsession.Datatask with Request Block Not Called in Background
Getting Client Certificate to Work for Mutual Authentication Using Swift 3 and Alamofire 4
iOS 7 Uitextview Vertical Alignment
Type 'Any' Has No Subscript Members (Firebase)
Does This App Use the Advertising Identifier (IDFA)? - Admob 6.8.0
Change Color of Back Button in Navigation Bar
Uitableviewcell Buttons with Action
Why am I Getting Ibtool Failed with Exit Code 255
When to Use Takeunretainedvalue() or Takeretainedvalue() to Retrieve Unmanaged Objects in Swift