Search code examples
swiftpush-notificationapple-push-notificationsappdelegate

Push notifications doesn't work properly, when app in background, Swift


I've added push notifications in my app. They serve to open a specific screen, when user presses in. It works fine, when app is completely closed and, when app is opened in foreground. But, when it's on background, first screen is open by pressing push instead of needed one.

Here, in AppDelegate, I work with push, when app is closed:

let pushManager = PushNotificationManager(userID: "UserID")
    pushManager.registerForPushNotifications()

    let notificationOption = launchOptions?[.remoteNotification]

    if let notification = notificationOption as? [String: AnyObject],
        let aps = notification["aps"] as? [String: AnyObject] {
        print(aps)
        let storyboard = UIStoryboard(name: "Invoice", bundle: nil)
        guard let returnPage = storyboard.instantiateViewController(withIdentifier:
            "\(InvoiceViewController.self)") as? InvoiceViewController else { return true }
        if let navBar = self.window?.rootViewController as? UINavigationController {
            navBar.pushViewController(returnPage, animated: true)
        }
    }

And here, also in AppDelegate, I work with push, when app is open:

func application(
  _ application: UIApplication,
  didReceiveRemoteNotification userInfo: [AnyHashable: Any],
  fetchCompletionHandler completionHandler:
  @escaping (UIBackgroundFetchResult) -> Void
) {
  guard let aps = userInfo["aps"] as? [String: AnyObject] else {
    completionHandler(.failed)
    return
  }

    let storyboard = UIStoryboard(name: "Invoice", bundle: nil)
            guard let returnPage = storyboard.instantiateViewController(withIdentifier:
                "\(InvoiceViewController.self)") as? InvoiceViewController else { return }
    if let navBar = self.window?.rootViewController as? UINavigationController {
        navBar.pushViewController(returnPage, animated: true)
    }
  print(aps)
}

Solution

  • You should use below code to handle responses of user on a push notification.

    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                    didReceive response: UNNotificationResponse,
                                    withCompletionHandler completionHandler: @escaping () -> Void) {
    // handle it here
    }
    

    This is part of UNUserNotificationCenterDelegate and works specifically for user-responses so you don't have to care about app state as well. I hope it will help.

    Edit: To use it, first register like that in didFinishLaunching

    let replyAction = UNTextInputNotificationAction(identifier: identifier,
                                                            title: "Reply",
                                                   options:.authenticationRequired, textInputButtonTitle: "Button", textInputPlaceholder: "")
    
    let newMessageCategory = UNNotificationCategory(identifier: someIdentifier,
                                                            actions: [replyAction],
                                                            intentIdentifiers: [],
                                                            options: [])
    
            UNUserNotificationCenter.current().setNotificationCategories([newMessageCategory])
    UNUserNotificationCenter.current().delegate = self
    

    And then register for the method above mentioned. You will get some info like below in parameters:

    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                    didReceive response: UNNotificationResponse,
                                    withCompletionHandler completionHandler: @escaping Func0) {
            let userInfo = response.notification.request.content.userInfo
            let actionIdentifier = response.actionIdentifier
    
            if actionIdentifier == UNNotificationDefaultActionIdentifier {
                  // handle navigation here
               }
    
            } 
    }