收到 iOS 推送通知时打开视图控制器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20757362/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Open a view controller when a iOS push notification is received
提问by cdsoft
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, only the application opens, but it does not redirect to a specific view controller.
我想在用户单击收到的推送通知消息时打开特定的视图控制器,但是当我收到推送通知消息并单击该消息时,只有应用程序打开,但它不会重定向到特定的视图控制器。
My code is
我的代码是
-(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];
}
}
My question is related with the iOS push notifications.
我的问题与 iOS 推送通知有关。
回答by staticVoidMan
You may be having issues with the if (applicationIsActive)
condition.
您的if (applicationIsActive)
病情可能有问题。
Put a breakpoint on -didReceiveRemoteNotification
and see whether it executes in different scenarios and see if it goes within the if-condition.
把一个断点-didReceiveRemoteNotification
,并看它是否在不同情况下执行,看看是否是不言而喻的范围内,如果-condition。
(unrelated to a certain extent but worth checking) this question:
didReceiveRemoteNotification when in background
(在一定程度上无关但值得检查)这个问题:
didReceiveRemoteNotification when in background
Note:
笔记:
-didReceiveRemoteNotification
will not execute if your app was (initially) closed and you clicked on the push notification to open the app.
This method executes when a push notification is received while the application is in the foreground or when the app transitions from background to foreground.
-didReceiveRemoteNotification
如果您的应用程序(最初)关闭并且您单击推送通知以打开应用程序,则不会执行。
当应用程序在前台或应用程序从后台转换到前台时收到推送通知时,将执行此方法。
Apple Reference: https://developer.apple.com/documentation/uikit/uiapplicationdelegate
苹果参考:https: //developer.apple.com/documentation/uikit/uiapplicationdelegate
If the app is running and receives a remote notification, the app calls this method to process the notification. Your implementation of this method should use the notification to take an appropriate course of action.
...
If the app is not running when a push notification arrives, the method launches the app and provides the appropriate information in the launch options dictionary. The app does not call this method to handle that push notification. Instead, your implementation of the application:willFinishLaunchingWithOptions:or application:didFinishLaunchingWithOptions:method needs to get the push notification payload data and respond appropriately.
如果应用程序正在运行并收到远程通知,则应用程序调用此方法来处理通知。您对这个方法的实现应该使用通知来采取适当的行动。
...
如果推送通知到达时应用程序未运行,该方法将启动应用程序并在启动选项字典中提供适当的信息。应用程序不会调用此方法来处理该推送通知。相反,您的 application:willFinishLaunchingWithOptions:或 application:didFinishLaunchingWithOptions:方法的实现需要获取推送通知有效负载数据并做出适当的响应。
So... When the app is not runningand a push notification is received, when the user clicks on the push notification, the app is launched and now... the push notification contents will be available in the -didFinishLaunchingWithOptions:
method in it's launchOptions
parameter.
所以......当应用程序没有运行并且收到推送通知时,当用户点击推送通知时,应用程序被启动,现在......推送通知内容将-didFinishLaunchingWithOptions:
在其launchOptions
参数的方法中可用。
In other words... -didReceiveRemoteNotification
won't execute this time and you'll also need to do this:
换句话说......-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
}
//...
}
Also read Apple's Doc on Handling Local and Remote Notifications
回答by Toseef Khilji
There is an extra space in the identifier name. Remove it and try:
标识符名称中有一个额外的空格。删除它并尝试:
UIStoryboard *mainstoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
PushBildirimlerim* pvc = [mainstoryboard instantiateViewControllerWithIdentifier:@"PushBildirimlerim"];
[self.window.rootViewController presentViewController:pvc animated:YES completion:NULL];
回答by iShwar
I was having same problem that when app is suspended/terminated and push notification arrives my app was only opening and not redirecting to specific screen corresponding to that notification the solution is,
我遇到了同样的问题,当应用程序被暂停/终止并且推送通知到达时,我的应用程序只是打开而不是重定向到与该通知对应的特定屏幕,解决方案是,
in
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
this method the parameter launchOptions
tells us if it has the notification by checking that we need to call the method to redirect to specific screen
在
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
这个方法中,参数launchOptions
通过检查我们是否需要调用重定向到特定屏幕的方法来告诉我们它是否有通知
the code is as below...
代码如下...
- (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;
}
then in the method showOfferNotification:notification you can redirect user to corresponding screen like...
然后在 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];
}
}
回答by Nishigandha Ahire
In Swift 4
在斯威夫特 4
If you need to achieve the above case you have to handle 2 cases
如果您需要实现上述情况,则必须处理2种情况
- When your app is in the background/Foreground state(if push notification is not silenced)
- 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.
如果有超过 1 种类型的通知,我在这里使用 category(推送通知有效负载中的内置参数来识别通知类型)。如果您只有一种类型的通知,则无需检查类别。
So for handling the first case, the code is as follows in AppDelegate File
所以对于第一种情况的处理,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
对于方法 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)
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.
对于方法 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)
}
}
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.
您可以浏览此博客 -如何在用户点击收到的推送通知时打开特定的视图控制器?以供参考。