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...
}
}
}