In which method should I handle iOS remote notification?

iOS 10 and later:

1) userNotificationCenter willPresent notification: Generally used to decide what to do when user is already inside the app and a notification arrives. You could possibly trigger a remote notification inside the app. After the user taps on the remote notification, method 2 (didReceive response) gets called.

@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (_ options: UNNotificationPresentationOptions) -> Void) {

//Handle push from foreground
//When a notification arrives and your user is using the app, you can maybe notify user by showing a remote notification by doing this
completionHandler([.alert, .badge, .sound])

//To print notification payload:
print(notification.request.content.userInfo)

}

2) userNotificationCenter didReceive response: Generally used to redirect the user to a particular screen of the app after user taps on the notification.

@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

//Handle push from background or closed (or even in foreground)
//This method is called when user taps on a notification

//To print notification payload:
print(response.notification.request.content.userInfo)

}

Below iOS 10:

3) application didReceiveRemoteNotification:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

    //To print notification payload
    print(userInfo)

    if #available(iOS 10.0, *) {
            
    }
    else {
             
        //Handle remote notifications for devices below iOS 10

        if application.applicationState == .active {
        //app is currently in foreground

        }
        else if application.applicationState == .background {
        //app is in background

        }
        else if application.applicationState == .inactive {
        //app is transitioning from background to foreground (user taps notification)

        }
    }
}

4) application didFinishLaunchingWithOptions launchOptions: The only scenario which is left for devices below iOS 10 is when app is closed and user taps on the notification launching the app. You'll have to check the following method for this scenario.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//To print notification payload:
    if let notification = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? [AnyHashable: Any] {
        print(notification)
    }
}

LaunchOptions is a dictionary indicating the reason the app was launched (if any). The contents of this dictionary may be empty in situations where the user launched the app directly.

Now to answer your questions,

  1. To handle a remote notification when app is in background/inactive, you'll have to add your code in method 2 (userNotificationCenter didReceive response) for devices with iOS 10 and above. Also, you'll have to use method 3 (application didReceiveRemoteNotification) for devices below iOS 10.

  2. To handle remote notifications when app is running in foreground before iOS 10, use the method 3 active state.