Open a view controller when a iOS push notification is received

前端 未结 4 1889
挽巷
挽巷 2020-11-29 01:09

I want to open a specific view controller when a user clicks on the received push notification message, but when I receive a push notification message and click the message,

4条回答
  •  自闭症患者
    2020-11-29 01:50

    In Swift 4

    If you need to achieve the above case you have to handle 2 cases

    1. When your app is in the background/Foreground state(if push notification is not silenced)
    2. When your app is in the inactive state

    Here I am using category(built in parameter in the payload of push notification to identify the type of notification) if there are more than 1 type of notifications. In case you have only 1 type of notification then no need to check for the category.

    So for handling the first case, the code is as follows in AppDelegate File

         func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {  
         let userInfo = response.notification.request.content.userInfo  
         let title = response.notification.request.content.title 
    
      //Method- 1 -- By using NotificationCenter if you want to take action on push notification on particular View Controllers
         switch response.notification.request.content.categoryIdentifier  
         {  
          case "Second":  
           NotificationCenter.default.post(name: NSNotification.Name(rawValue: "SecondTypeNotification"), object: title, userInfo: userInfo)  
           break  
          case "Third":  
           NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ThirdTypeNotification"), object: title, userInfo: userInfo)  
           break  
           default:  
            break  
         }
    
    ///Method -2 --- Check the view controller at the top and then push to the required View Controller
    
    
                if let currentVC = UIApplication.topViewController() {
                    //the type of currentVC is MyViewController inside the if statement, use it as you want to
                    if response.notification.request.content.categoryIdentifier == "Second"
                    {
                        let storyboard = UIStoryboard(name: "Main", bundle: nil)
                        let vc: SecondViewController = storyboard.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
                        currentVC.navigationController?.pushViewController(vc, animated: true)
                    }
                    else if response.notification.request.content.categoryIdentifier == "Third"
                    {
                        let storyboard = UIStoryboard(name: "Main", bundle: nil)
                        let vc: ThirdViewController = storyboard.instantiateViewController(withIdentifier: "ThirdViewController") as! ThirdViewController
                        currentVC.navigationController?.pushViewController(vc, animated: true)
                    }
    
                }
    
    
    
         completionHandler()  }  
    

    For Method 1- After which you have to add the observers in the default view controller as follows in viewDidLoad

         NotificationCenter.default.addObserver(self,selector: #selector(SecondTypeNotification),  
                         name: NSNotification.Name(rawValue: "SecondTypeNotification"),  
                         object: nil)
         NotificationCenter.default.addObserver(self,selector:#selector(ThirdTypeNotification),  
                         name: NSNotification.Name(rawValue: "ThirdTypeNotification"),  
                         object: nil) 
    

    For Method 1- And also need two add the Notification observer function for adding actions to be executed with the same name used in Observer.

        // Action to be taken if push notification is opened and observer is called while app is in background or active
         @objc func SecondTypeNotification(notification: NSNotification){  
     DispatchQueue.main.async  
       {  
         //Land on SecondViewController  
         let storyboard = UIStoryboard(name: "Main", bundle: nil)  
         let vc: SecondViewController = storyboard.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController  
         self.navigationController?.pushViewController(vc, animated: true)  
       }   
        }
         @objc func ThirdTypeNotification(notification: NSNotification){  
     DispatchQueue.main.async  
       {  
         //Land on SecondViewController  
         let storyboard = UIStoryboard(name: "Main", bundle: nil)  
         let vc: ThirdViewController = storyboard.instantiateViewController(withIdentifier: "ThirdViewController") as! ThirdViewController  
         self.navigationController?.pushViewController(vc, animated: true)  
       }  
           }
    

    So whenever a notification is opened when the app is in the foreground or background the above will execute and move to respective view controller according to the category in the payload.

    Now the second case

    We know that when the app is inactive the first function that will be called when the push notification is opened is

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

    So we have to check in this function whether the app is launched by opening push notification or by clicking the app icon. For this, there is a provision provided to us. The function will look as follows after adding the required code.

            func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {  
         FirebaseApp.configure()  
         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 })  
         } else {  
           let settings: UIUserNotificationSettings =  
             UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)  
           application.registerUserNotificationSettings(settings)  
         }  
         // Register the notification categories.  
         application.registerForRemoteNotifications()  
         Messaging.messaging().delegate = self  
         /// Check if the app is launched by opening push notification  
         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: "category") 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  
    
    
    // Method - 1
           if category == "Second"  
           {  
             /// 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 == "Third"  
           {  
            AppConstants.sharedInstance.userDefaults.set(true, forKey: AppConstants.sharedInstance.kisFromNotificationThird)  
           } 
    
    
    // Method 2: Check top view controller and push to required view controller
     if let currentVC = UIApplication.topViewController() {
           if category == "Second"
           {
             let storyboard = UIStoryboard(name: "Main", bundle: nil)
             let vc: SecondViewController = storyboard.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
             currentVC.navigationController?.pushViewController(vc, animated: true)
           }
           else if category == "Third"
           {
             let storyboard = UIStoryboard(name: "Main", bundle: nil)
             let vc: ThirdViewController = storyboard.instantiateViewController(withIdentifier: "ThirdViewController") as! ThirdViewController
             currentVC.navigationController?.pushViewController(vc, animated: true)
            }
    
          } 
        }  
         return true  
     }  
    
    For Method 1-
    After this, check these flags value in the default view controller in viewdidLoad as follows
    
            if AppConstants.sharedInstance.userDefaults.bool(forKey: AppConstants.sharedInstance.kisFromNotificationSecond) == true  
         {  
           //Land on SecondViewController  
           let storyboard = UIStoryboard(name: "Main", bundle: nil)  
           let vc: SecondViewController = storyboard.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController  
           self.navigationController?.pushViewController(vc, animated: true)  
           AppConstants.sharedInstance.userDefaults.set(false, forKey: AppConstants.sharedInstance.kisFromNotificationSecond)  
         }  
         if AppConstants.sharedInstance.userDefaults.bool(forKey: AppConstants.sharedInstance.kisFromNotificationThird) == true  
         {  
           //Land on SecondViewController  
           let storyboard = UIStoryboard(name: "Main", bundle: nil)  
           let vc: ThirdViewController = storyboard.instantiateViewController(withIdentifier: "ThirdViewController") as! ThirdViewController  
           self.navigationController?.pushViewController(vc, animated: true)  
           AppConstants.sharedInstance.userDefaults.set(false, forKey: AppConstants.sharedInstance.kisFromNotificationThird)  
         }  
    

    This will achieve the goal to open a particular view controller when the push notification is opened.

    You can go through this blog- How to open a particular View Controller when the user taps on the push notification received? for reference.

提交回复
热议问题