web-dev-qa-db-fra.com

Ouvrir un contrôleur de vue lorsqu'une notification iOS Push est reçue

Je souhaite ouvrir un contrôleur de vue spécifique lorsqu'un utilisateur clique sur le message de notification Push reçu, mais lorsque je reçois un message de notification Push et que je clique sur le message, seule l'application s'ouvre, mais elle ne redirige pas vers un contrôleur de vue spécifique.

Mon code est

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    if (applicationIsActive) {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Bildirim"
                                                            message:[NSString stringWithFormat:@"%@ ",[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]]
                                                           delegate:self cancelButtonTitle:@"Ok" 
                                                  otherButtonTitles:nil];
        [alertView show];

        UIViewController *vc = self.window.rootViewController;
        PushBildirimlerim *pvc = [vc.storyboard instantiateViewControllerWithIdentifier:@"PushBildirimlerim "];

        [vc presentViewController:pvc animated:YES completion:nil];
     }
}

Ma question concerne les notifications push iOS.

26
cdsoft

Vous pouvez avoir des problèmes avec la condition if (applicationIsActive)

Placez un point d'arrêt sur -didReceiveRemoteNotification et voyez s'il s'exécute dans différents scénarios et voyez s'il entre dans la condition if-.

(non apparenté dans une certaine mesure mais mérite d'être vérifié) cette question:
didReceiveRemoteNotification en arrière-plan


Remarque:

-didReceiveRemoteNotification ne sera pas exécuté si votre application était fermée (initialement) et que vous avez cliqué sur la notification Push pour ouvrir l'application.
Cette méthode est exécutée lorsqu'une notification Push est reçue alors que l'application est au premier plan ou lorsque l'application passe de l'arrière-plan à l'avant-plan.

Référence Apple: https://developer.Apple.com/documentation/uikit/uiapplicationdelegate

Si l'application est en cours d'exécution et reçoit une notification à distance, l'application appelle cette méthode pour traiter la notification. Votre implémentation de cette méthode doit utiliser la notification pour suivre un cours approprié d'action.
...
Si l'application ne s'exécute pas lorsqu'une notification Push arrive, la méthode lance l'application et fournit les informations appropriées dans le fichier lance le dictionnaire des options. L'application n'appelle pas cette méthode pour gérer cette notification Push. Au lieu de cela, votre implémentation du application: willFinishLaunchingWithOptions: ou application: didFinishLaunchingWithOptions: La méthode doit obtenir le Poussez les données de notification et répondez de manière appropriée.


Alors ... Lorsque l'application est non en cours d'exécution et qu'une notification Push est reçue, lorsque l'utilisateur clique sur la notification Push, l'application est lancée et maintenant... la notification Push le contenu sera disponible dans la méthode -didFinishLaunchingWithOptions: dans son paramètre launchOptions

En d'autres termes ... -didReceiveRemoteNotification n'exécutera pas cette heure et vous devrez également le faire:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //...
    NSDictionary *userInfo = [launchOptions valueForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"];
    NSDictionary *apsInfo = [userInfo objectForKey:@"aps"];

    if(apsInfo) {
        //there is some pending Push notification, so do something
        //in your case, show the desired viewController in this if block
    }
    //...
}

Lire aussi le document d'Apple sur le traitement des notifications locales et distantes

44
staticVoidMan

Il y a un espace supplémentaire dans le nom de l'identifiant. Supprimez-le et essayez:

UIStoryboard *mainstoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
PushBildirimlerim* pvc = [mainstoryboard instantiateViewControllerWithIdentifier:@"PushBildirimlerim"];
[self.window.rootViewController presentViewController:pvc animated:YES completion:NULL];
6
Toseef Khilji

J'avais le même problème que lorsque l'application est suspendue/arrêtée et que la notification Push arrive, mon application ne faisait que s'ouvrir et ne pas être redirigé vers un écran spécifique correspondant à cette notification de la solution 

dans - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions cette méthode, le paramètre launchOptions nous indique si elle dispose de la notification en vérifiant que nous devons appeler la méthode pour la rediriger vers un écran spécifique

le code est comme ci-dessous ...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //your common or any code will be here at last add the below code..

    NSMutableDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];

    if (notification)
    {
//this notification dictionary is same as your JSON payload whatever you gets from Push notification you can consider it as a userInfo dic in last parameter of method -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
        NSLog(@"%@",notification);
        [self showOfferNotification:notification];
    }

     return YES;
}

puis dans la méthode showOfferNotification: notification, vous pouvez rediriger l'utilisateur vers l'écran correspondant comme ...

//** added code for notification
-(void)showOfferNotification:(NSMutableDictionary *)offerNotificationDic{
//This whole is my coding stuff.. your code will come here..
    NSDictionary *segueDictionary = [offerNotificationDic valueForKey:@"aps"];

    NSString *segueMsg=[[NSString alloc]initWithFormat:@"%@",[segueDictionary valueForKey:@"alert"]];

    NSString *segueID=[[NSString alloc]initWithFormat:@"%@",[offerNotificationDic valueForKey:@"id"]];

    NSString *segueDate=[[NSString alloc]initWithFormat:@"%@",[offerNotificationDic valueForKey:@"date"]];

    NSString *segueTime=[[NSString alloc]initWithFormat:@"%@",[offerNotificationDic valueForKey:@"time"]];

    NSLog(@"Show Offer Notification method : segueMsg %@ segueDate %@ segueTime %@ segueID %@",segueMsg,segueDate,segueTime,segueID);

    if ([segueID isEqualToString:@"13"]){

        NSString *advertisingUrl=[[NSString alloc]initWithFormat:@"%@",[offerNotificationDic valueForKey:@"advertisingUrl"]];

        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        [defaults setObject:segueMsg forKey:@"notificationMsg"];
        [defaults setObject:segueDate forKey:@"notifcationdate"];
        [defaults setObject:segueTime forKey:@"notifcationtime"];
        [defaults setObject:advertisingUrl forKey:@"advertisingUrl"];
        [defaults synchronize];

        navigationController = (UINavigationController *)self.window.rootViewController;
        UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main_iPhone" bundle: nil];
        FLHGAddNotificationViewController *controller = (FLHGAddNotificationViewController*)[mainStoryboard instantiateViewControllerWithIdentifier: @"offerViewController"];
        [navigationController pushViewController:controller animated:YES];
    }
}
2
iShwar

Dans Swift 4

Si vous avez besoin de réaliser le cas ci-dessus, vous devez gérer 2 cas

  1. Lorsque votre application est à l'état d'arrière-plan/avant-plan (si la notification Push N'est pas désactivée) 
  2. Lorsque votre application est inactive

Ici, je me sers de la catégorie (paramètre intégré dans la charge de notification Push pour identifier le type de notification) s’il existe plus d’un type de notification. Dans le cas où vous n’avez qu’un seul type de notification, inutile de vérifier la catégorie.

Donc pour traiter le premier cas, le code est le suivant dans 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  
 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  
 }  
 completionHandler()  }  

Après quoi, vous devez ajouter les observateurs dans le contrôleur de vue par défaut comme suit dans 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) 

Et également besoin de deux ajouter la fonction d'observation de notification pour ajouter des actions à exécuter avec le même nom utilisé dans 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)  
   }  
       }

Ainsi, chaque fois qu'une notification est ouverte lorsque l'application est au premier plan ou à l'arrière-plan, la procédure ci-dessus est exécutée et déplacée vers le contrôleur de vue correspondant en fonction de la catégorie dans la charge utile.

Maintenant le deuxième cas

Nous savons que lorsque l'application est inactive, la première fonction qui sera appelée lors de l'ouverture de la notification Push est

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

Nous devons donc vérifier dans cette fonction si l'application est lancée en ouvrant la notification Push ou en cliquant sur l'icône de l'application. Pour cela, une disposition nous est fournie. La fonction se présentera comme suit après avoir ajouté le code requis.

    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  
   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)  
   }  
 }  
 return true  
   }  

Ensuite, vérifiez la valeur de ces indicateurs dans le contrôleur de vue par défaut dans viewdidLoad comme suit

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

Cela permettra d’ouvrir un contrôleur de vue particulier lorsqu’une notification Push sera ouverte.

Vous pouvez passer par ce blog- Comment ouvrir un View Controller particulier lorsque l'utilisateur appuie sur la notification Push reçue? pour référence. 

0
Nishigandha Ahire