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

时间:2013-12-24 08:19:27

标签: ios cocoa-touch push-notification appdelegate

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

我的代码是

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

5 个答案:

答案 0 :(得分:44)

您可能遇到if (applicationIsActive)条件的问题。

-didReceiveRemoteNotification上设置一个断点,看看它是否在不同情况下执行,看看它是否在 if 条件下。

在某种程度上无关但值得检查)这个问题:
didReceiveRemoteNotification when in background


注意:

如果您的应用(最初)已关闭,并且您点击推送通知以打开应用,则

-didReceiveRemoteNotification将无法执行。
当应用程序在前台或应用程序从后台转换为前台时收到推送通知时,将执行此方法。

Apple参考:https://developer.apple.com/documentation/uikit/uiapplicationdelegate

  

如果应用正在运行并收到远程通知,则应用   调用此方法来处理通知。你的实施   此方法应使用通知采取适当的方法   行动   ...
  如果在推送通知到达时应用程序未运行,则该方法   启动应用程序并提供相应的信息   启动选项字典。该应用程序不会调用此方法来处理   推送通知。相反,你的实施   应用程序:willFinishLaunchingWithOptions:或   应用程序:didFinishLaunchingWithOptions:方法需要获取   推送通知有效载荷数据并做出适当的响应。


所以...当应用未运行且收到推送通知时,当用户点击推送通知时,该应用就会启动,现在。 ..推送通知内容将在其-didFinishLaunchingWithOptions:参数的launchOptions方法中提供。

换句话说...... -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's Doc on Handling Local and Remote Notifications

答案 1 :(得分:6)

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

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

答案 2 :(得分:2)

我遇到同样的问题,当应用程序暂停/终止并且推送通知到达时,我的应用程序只是打开而不是重定向到与该通知相对应的特定屏幕解决方案,

- (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:通知你可以将用户重定向到相应的屏幕,如...

//** 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];
    }
}

答案 3 :(得分:2)

在Swift 4中

如果需要实现上述情况,则必须处理2种情况

  1. 当您的应用处于后台/前景状态时(如果按 通知未关闭)
  2. 当您的应用处于非活动状态时

在这里,我使用类别(推送通知的有效负载中的内置参数来标识通知的类型),如果通知类型超过一种。如果您只有一种类型的通知,则无需检查类别。

因此,对于第一种情况,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

中的默认视图控制器中添加观察者。
     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 并且还需要两个添加Notification Observer的功能,以添加要与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)  
   }  
       }

因此,只要在应用程序处于前台或后台时打开通知,上述内容就会根据有效内容中的类别执行并移至相应的视图控制器。

现在是第二种情况

我们知道,当应用程序处于非活动状态时,打开推送通知时将调用的第一个功能是

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

这将达到在打开推送通知时打开特定视图控制器的目的。

您可以浏览此博客-How to open a particular View Controller when the user taps on the push notification received?以供参考。

答案 4 :(得分:0)

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

func userNotificationCenter(_中心:UNUserNotificationCenter,didReceive响应:UNNotificationResponse,带有CompletionHandlercompleteHandler:@escaping()-> Void){

    let nav = UINavigationController()
    nav.navigationBar.isHidden = true
    let first = Router.shared.splashVC()
    let sceond = Router.shared.CustomTabbarVC()
    let third = Router.shared.ProviderDetailsVC()
    sceond.selectedIndex = 2
    nav.viewControllers = [first,sceond,third]
    UIApplication.shared.keyWindow?.rootViewController = nav
    UIApplication.shared.keyWindow?.makeKeyAndVisible()

}