iosapple-push-notificationsswift4.2

How to Open a Notification view controller when a iOS push notification is received?


I am working in swift 4.2, and Push notification receive from FireBase. When I tap the Notification, it go to Homepage. But I want to go to Notification page.

This is Swift4.2, Xcode 9.3, iOS 12.1. In the past , I have tried but not working both Foreground and InActive the app

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        FirebaseApp.configure()

        UINavigationBar.appearance().barTintColor = UIColor(red: 0/255.0, green: 85/255.0, blue: 127/255.0, alpha: 1)
        UINavigationBar.appearance().tintColor = UIColor.white
        //        UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor : UIColor.white,NSAttributedString.Key.font: UIFont(name: "Roboto-Medium", size: 16)!]
        UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffset(horizontal: 0, vertical: -60), for:UIBarMetrics.default)
        UINavigationBar.appearance().isTranslucent = false

        UIApplication.shared.statusBarStyle = .lightContent

        IQKeyboardManager .shared().isEnabled = true
        IQKeyboardManager .shared().shouldResignOnTouchOutside = true
        IQKeyboardManager .shared().isEnableAutoToolbar = false

        if let notification = launchOptions?[.remoteNotification] as? [String: AnyObject] {

            // If your app wasn’t running and the user launches it by tapping the push notification, the push notification is passed to your app in the launchOptions

            let aps = notification["aps"] as! [String: AnyObject]
            UIApplication.shared.applicationIconBadgeNumber = 0


        }            

        if #available(iOS 10.0, *) {
            UNUserNotificationCenter.current().delegate = self
            let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
            UNUserNotificationCenter.current().requestAuthorization(
                options: authOptions,
                completionHandler: {_, _ in })
        } else {
            let settings: UIUserNotificationSettings =
                UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
            application.registerUserNotificationSettings(settings)
        }

        application.registerForRemoteNotifications()


        let mainview = UIStoryboard(name:"Main", bundle: nil).instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
        let nav = UINavigationController.init(rootViewController: mainview)
        SideMenu = LGSideMenuController.init(rootViewController: nav)
        SideMenuView = UIStoryboard(name:"Main", bundle: nil).instantiateViewController(withIdentifier: "SideMenuViewController") as! SideMenuViewController
        SideMenu.rightViewStatusBarVisibleOptions = .onAll
        let rect = SideMenuView.view.frame;
        SideMenuView.view.frame = rect


        Messaging.messaging().delegate = self
        //        Siren.shared.wail()

        if launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification] != nil {
            // Do your task here
            let dic = launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification] as? NSDictionary
            let dic2 = dic?.value(forKey: "aps") as? NSDictionary
            let alert = dic2?.value(forKey: "alert") as? NSDictionary
            let category = dic2?.value(forKey: "title") as? String
            // We can add one more key name 'click_action' in payload while sending push notification and check category for indentifying the push notification type. 'category' is one of the seven built in key of payload for identifying type of notification and take actions accordingly
            if category == "News Added"
            {
                /// Set the flag true for is app open from Notification and on root view controller check the flag condition to take action accordingly
                AppConstants.sharedInstance.userDefaults.set(true, forKey: AppConstants.sharedInstance.kisFromNotificationSecond)
            }
            else if category == "1-2-1 notification"
            {
                AppConstants.sharedInstance.userDefaults.set(true, forKey: AppConstants.sharedInstance.kisFromNotificationThird)
            }
        }


        return true
    }

Solution

  • For Kill State OR Terminate State:

    Define new property in AppDelegate.swift file

    var isFromNotification = false
    

    Make below changes in AppDelegate.swift and keep rest of code as it is.

    if launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification] != nil {
        isFromNotification = true
        //other required code
    }
    

    Goto your Homepage.swift file

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated).
        
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        if appDelegate.isFromNotification {
            appDelegate.isFromNotification = false
            //Push to your notification controler without animation
        }
    }
    

    Update: For Background and Foreground State

    Above answer is only work for Kill state as mention in the comment by @Abu Ul Hassan

    Now, Let's understand the flow about the background or foreground state.

    userNotificationCenter(_:didReceive:withCompletionHandler:) method is called when a user clicks on the notification in background or foreground mode.

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        //other required code
        //Get current navigation controller and redirect into notification screen
        completionHandler()
    }
    

    How to grab current UIViewController or current UINavigationController