web-dev-qa-db-ja.com

iOSプッシュ通知を受信したときにView Controllerを開きます

ユーザーが受信したプッシュ通知メッセージをクリックしたときに特定のView Controllerを開きたいのですが、プッシュ通知メッセージを受信して​​メッセージをクリックすると、アプリケーションのみが開きますが、特定のView Controllerにリダイレクトされません。

私のコードは

-(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];
     }
}

私の質問は、iOSプッシュ通知に関連しています。

28
cdsoft

if (applicationIsActive)状態に問題がある可能性があります。

-didReceiveRemoteNotificationにブレークポイントを設定し、異なるシナリオで実行されるかどうかを確認し、if-条件内に収まるかどうかを確認します。

ある程度は無関係だがチェックする価値がある)この質問:
バックグラウンドでのdidReceiveRemoteNotification


注意:

-didReceiveRemoteNotificationは、アプリが(initially)閉じられ、プッシュ通知をクリックしてアプリを開くと実行されません。
このメソッドは、アプリケーションがフォアグラウンドにあるときにプッシュ通知を受信したとき、またはアプリケーションがバックグラウンドからフォアグラウンドに移行したときに実行されます。

Appleリファレンス: https://developer.Apple.com/documentation/uikit/uiapplicationdelegate

アプリが実行中で、リモート通知を受信した場合、アプリはこのメソッドを呼び出して通知を処理します。このメソッドの実装では、通知を使用して適切な一連のアクションを実行する必要があります。
...
プッシュ通知の到着時にアプリが実行されていない場合、メソッドはアプリを起動し、起動オプション辞書に適切な情報を提供します。アプリは、そのプッシュ通知を処理するためにこのメソッドを呼び出しません。代わりに、application:willFinishLaunchingWithOptions:またはapplication:didFinishLaunchingWithOptions:メソッドは、プッシュ通知ペイロードデータを取得し、適切に応答する必要があります。


だから...アプリが実行されていないときにプッシュ通知が受信され、ユーザーがプッシュ通知をクリックすると、アプリが起動してnow...プッシュ通知の内容は、launchOptionsパラメーターの-didFinishLaunchingWithOptions:メソッドで利用できます。

言い換えると... -didReceiveRemoteNotificationは今回は実行されず、これも実行する必要があります。

- (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
    }
    //...
}

ローカルおよびリモート通知の処理に関するAppleのドキュメント も読んでください

44
staticVoidMan

識別子名に余分なスペースがあります。削除して試してください:

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

私は同じ問題を抱えていました。アプリが中断/終了し、プッシュ通知が届くと、アプリは開いているだけで、その通知に対応する特定の画面にリダイレクトされず、ソリューションは、

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptionsこのメソッドのパラメーターlaunchOptionsは、特定の画面にリダイレクトするためにメソッドを呼び出す必要があることを確認することで、通知があるかどうかを通知します

コードは以下の通りです...

- (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;
}

次に、メソッドshowOfferNotification:notificationで、次のような対応する画面にユーザーをリダイレクトできます。

//** 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

In Swift 4

上記のケースを達成する必要がある場合は、2つのケースを処理する必要があります

  1. アプリがバックグラウンド/フォアグラウンド状態の場合(プッシュ通知が無音でない場合)
  2. アプリが非アクティブ状態のとき

ここでは、複数の種類の通知がある場合、カテゴリ(プッシュ通知のペイロードの組み込みパラメーターで通知の種類を識別する)を使用しています。 1種類の通知しかない場合は、カテゴリを確認する必要はありません。

したがって、最初のケースを処理するためのコードは、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() {

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

方法1の場合-その後、viewDidLoadで次のようにデフォルトのView Controllerにオブザーバーを追加する必要があります

     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) 

方法1の場合-また、オブザーバーで使用されるのと同じ名前で実行されるアクションを追加するための通知オブザーバー関数を2つ追加する必要があります。

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

そのため、アプリがフォアグラウンドまたはバックグラウンドにあるときに通知が開かれるたびに、上記が実行され、ペイロードのカテゴリに従ってそれぞれのView Controllerに移動します。

2番目のケース

アプリが非アクティブの場合、プッシュ通知が開かれたときに呼び出される最初の関数は

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

そのため、プッシュ通知を開くかアプリのアイコンをクリックしてアプリを起動するかどうかをこの関数でチェックする必要があります。このために、規定が用意されています。必要なコードを追加すると、関数は次のようになります。

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

これにより、プッシュ通知が開かれたときに特定のView Controllerを開くという目標が達成されます。

このブログを読むことができます ユーザーが受信したプッシュ通知をタップしたときに特定のView Controllerを開く方法? .

2