收到iOS推送通知时打开视图控制器

收到iOS推送通知时打开视图控制器,ios,cocoa-touch,push-notification,appdelegate,Ios,Cocoa Touch,Push Notification,Appdelegate,当用户单击收到的推送通知消息时,我想打开特定的视图控制器,但当我收到推送通知消息并单击该消息时,只有应用程序打开,但它不会重定向到特定的视图控制器 我的代码是 -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { if (applicationIsActive) { UIAlertView *alertView = [[

当用户单击收到的推送通知消息时,我想打开特定的视图控制器,但当我收到推送通知消息并单击该消息时,只有应用程序打开,但它不会重定向到特定的视图控制器

我的代码是

-(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推送通知有关。

标识符名称中有一个额外的空格。请将其删除并尝试:

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

您可能在if(applicationIsActive)条件下遇到问题

-didReceiveEmotentification
上设置断点,查看它是否在不同的场景中执行,并查看它是否在if条件下运行

(与某种程度无关,但值得检查)这个问题:


注:
-如果您的应用程序(最初)关闭,并且您单击推送通知打开应用程序,则不会执行didReceiveRemoteNotification

当应用程序处于前台时收到推送通知,或者当应用程序从后台转换到前台时,将执行此方法

苹果参考:

如果应用程序正在运行并收到远程通知,则应用程序 调用此方法以处理通知。你实施的 此方法应使用通知选择适当的课程 行动纲领。

如果推送通知到达时应用程序未运行,则方法 启动应用程序并在中提供相应的信息 启动选项字典。应用程序未调用此方法来处理 那个推送通知。相反,您的 应用程序:将使用选项完成启动:应用程序:使用选项完成启动:方法需要获取 推送通知有效负载数据并适当响应


所以。。。当应用程序未运行且收到推送通知时,当用户单击推送通知时,应用程序启动且现在。。。推送通知内容将在其
launchOptions
参数的
-didfishlaunchwithoptions:
方法中可用

换句话说<代码>-DidReceiveMemotentification这次将不执行,您还需要执行以下操作:

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

另请阅读

我遇到了相同的问题,即当应用程序被挂起/终止并且推送通知到达时,我的应用程序只是打开,而没有重定向到与该通知对应的特定屏幕,解决方案是

-(BOOL)application:(UIApplication*)application didnishlaunchingwithoptions:(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];
    }
}

在Swift 4中

如果你需要达到上述情况,你必须处理2个案例

  • 当应用程序处于后台/前台状态时(如果推送 通知未被沉默)
  • 当您的应用处于非活动状态时
  • 在这里,如果有超过1种类型的通知,我将使用category(推送通知的有效负载中的内置参数来标识通知的类型)。如果您只有1种类型的通知,则无需检查类别

    因此,对于处理第一种情况,代码如下所示,在AppDelegate文件中

         func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -&gt; 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()  }  
    
    方法1- 之后,必须在默认视图控制器中添加观察者,如下所示

         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- 还需要两个添加通知观察者的函数,用于添加要使用观察者中使用的相同名称执行的操作

        // 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)  
       }  
           }
    
    因此,当应用程序位于前台或后台时,每当打开通知时,上述内容都将根据有效负载中的类别执行并移动到相应的视图控制器

    现在是第二种情况

         func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -&gt; 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()  }  
    
    我们知道,当应用程序处于非活动状态时,打开推送通知时将调用的第一个函数是

        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -&gt; Bool {  
     return true  
           }  
    
    因此,我们必须在此功能中检查应用程序是通过打开推送通知还是通过单击应用程序图标启动的。为此,向我们提供了一项规定。添加所需代码后,函数将如下所示

            func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -&gt; 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)  
         }  
    
    这将实现在打开推送通知时打开特定视图控制器的目标


    你可以浏览这个博客,以供参考

    点击通知时 呼叫通知委托功能

    func userNotificationCenter(center:UNUserNotificationCenter,didReceive响应:UNNotificationResponse,withCompletionHandler completionHandler:@escaping()->Void){


    }

    如果您的应用程序位于后台,并且由于用户触摸推送通知而进入前台,则应用程序不会经过
    应用程序操作:didFinishLaunchingWithOptions
    (因为它已经启动)并触发
    应用程序:DidReceiveMemotentification:
    谢谢您的回复,我使用了您的代码,并且我尝试了如果([apsInfo objectForKey:@“警报”!=NULL){推送至视图控制器}但当应用程序关闭时,应用程序将停留在主屏幕而不是消息视图中controller@cdsoft:对不起,我没有完全理解您的意思。当您单击推送通知并启动应用程序时,它将执行if条件,但当没有等待推送通知时,您的应用程序将正常启动。谢谢您的帮助,我使用了您的代码块,如up,我在didFinishLaunchingWithOptions中编写了相同的代码,并将重定向代码写入PushBilDirimLerm视图。如果应用程序已关闭,我单击“新建推送通知”,则应用程序将打开,但不会重定向PushB