Откройте диспетчер представлений, когда получено одноразовое уведомление iOS
Я хочу открыть определенный контроллер представления, когда пользователь нажимает на полученное сообщение push-уведомления, но когда я получаю push-уведомление и щелкаю сообщение, открывается только приложение, но оно не перенаправляется на определенный контроллер представления.
Мой код
-(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 push.
Ответы
Ответ 1
У вас могут возникнуть проблемы с условием if (applicationIsActive)
.
Поместите точку останова на -didReceiveRemoteNotification
и посмотрите, выполняется ли она в разных сценариях и посмотрите, идет ли она в if -condition.
(не связанный в определенной степени, но заслуживающий проверки) этот вопрос:
didReceiveRemoteNotification в фоновом режиме
Примечание:
-didReceiveRemoteNotification
не будет выполняться, если ваше приложение было (первоначально) закрыто, и вы нажали на push-уведомление, чтобы открыть приложение.
Этот метод выполняется, когда push-уведомление принимается, когда приложение находится на переднем плане или когда приложение переходит из фона на передний план.
Справочник Apple: https://developer.apple.com/documentation/uikit/uiapplicationdelegate
Если приложение запущено и получает удаленное уведомление, приложение вызывает этот метод для обработки уведомления. Ваша реализация этот метод должен использовать уведомление, чтобы пройти соответствующий курс действия.
...
Если приложение не запускается при поступлении push-уведомления, метод запускает приложение и предоставляет соответствующую информацию в словарь параметров запуска. Приложение не вызывает этот метод для обработки это толчок уведомление. Вместо этого ваша реализация приложение: willFinishLaunchingWithOptions: или приложение: didFinishLaunchingWithOptions: метод должен получить нажимать данные полезной нагрузки и реагировать соответствующим образом.
Итак... Когда приложение не работает и получено push-уведомление, когда пользователь нажимает на push-уведомление, приложение запускается и теперь... содержимое push-уведомления будет доступно в -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 Doc при обработке локальных и удаленных уведомлений
Ответ 2
В имени идентификатора есть дополнительное пространство. Удалите его и попробуйте:
UIStoryboard *mainstoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
PushBildirimlerim* pvc = [mainstoryboard instantiateViewControllerWithIdentifier:@"PushBildirimlerim"];
[self.window.rootViewController presentViewController:pvc animated:YES completion:NULL];
Ответ 3
У меня была такая же проблема, что, когда приложение приостановлено/завершено, а push-уведомление приходит, мое приложение только открывалось, а не перенаправлялось на конкретный экран, соответствующий этому уведомлению, это решение,
в
- (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];
}
}
Ответ 4
В Swift 4
Если вам нужно добиться вышеупомянутого случая, вы должны обработать 2 случая
- Когда ваше приложение находится в фоновом/переднем плане (если push-уведомление не отключено)
- Когда ваше приложение находится в неактивном состоянии
Здесь я использую категорию (встроенный параметр в полезных данных push-уведомлений для определения типа уведомлений), если существует более 1 типа уведомлений. В случае, если у вас есть только 1 тип уведомления, нет необходимости проверять категорию.
Таким образом, для обработки первого случая, код в файле AppDelegate выглядит следующим образом
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- А также необходимо два добавить функцию наблюдателя уведомлений для добавления действий, которые будут выполняться с тем же именем, которое используется в 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)
}
}
Таким образом, всякий раз, когда уведомление открывается, когда приложение находится на переднем плане или в фоне, вышеуказанное будет выполняться и перемещаться к соответствующему контроллеру представления в соответствии с категорией в полезной нагрузке.
Теперь второй случай
Мы знаем, что когда приложение неактивно, первая функция, которая будет вызываться при открытии push-уведомления,
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}
Поэтому мы должны проверить в этой функции, запущено ли приложение, открыв push-уведомление или щелкнув значок приложения. Для этого есть положение, предоставленное нам. Функция будет выглядеть следующим образом после добавления необходимого кода.
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)
}
Это позволит достичь цели открыть конкретный контроллер представления при открытии push-уведомления.
Вы можете пройти через это blog- Как открыть определенный View Controller, когда пользователь нажимает на полученное push-уведомление? для справки.
Ответ 5
Если вам нужно добиться вышеупомянутого случая, вы должны обработать 2 случая
- Когда ваше приложение находится в фоновом/переднем плане (если push-уведомления не отключены)
- Когда ваше приложение неактивно
S для обработки первого случая, который вы должны обработать в функции ниже.
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
completionHandler() }
И для обработки второго случая мы должны обработать его в следующей функции
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true }
Вы можете пройти через это Как открыть определенный View Controller, когда пользователь нажимает на полученное push-уведомление? чтобы понять поток правильно. Просто пройдите вышеуказанные 2 пункта.