在 iOS 中收到 APNS 时打开视图控制器中的问题

Posted

技术标签:

【中文标题】在 iOS 中收到 APNS 时打开视图控制器中的问题【英文标题】:Issue in open view controller when APNS is received in iOS 【发布时间】:2014-04-04 05:53:52 【问题描述】:

嘿,我是 iPhone 新手,我一直在尝试使用 Apple 推送通知。基本上,我想做的是当用户点击收到的推送通知消息时,我需要打开一个特定的视图控制器,它对我有用。我已将带有关键参数“类型”的自定义数据添加到我的有效负载 JSON。

这是我的有效载荷 JSON:

"aps":"alert":"This is testing message","type":"Notify","badge":1,"sound":"default"

这是我的代码:

@synthesize viewControllerNotify;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

    [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
    [[UIApplication sharedApplication] cancelAllLocalNotifications];

    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
     (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];

    screenBounds = [[UIScreen mainScreen] bounds];

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    if (launchOptions != nil) 
        //Launched from push notification

        NSDictionary *userInfo = [launchOptions valueForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"];
        NSDictionary *apsInfo = [userInfo objectForKey:@"aps"];

        NSMutableString *notificationType = [apsInfo objectForKey:@"type"];

        //For redirect to the view
        if([notificationType isEqualToString:@"Notify"])

            //Notify updates
            UpdatesViewController *uvc1 = [[UpdatesViewController alloc] initWithNibName:@"UpdatesViewController" bundle:nil];

            self.viewControllerNotify = uvc1;
        

        else if([notificationType isEqualToString:@"Voting"] || [notificationType isEqualToString:@"QA"])

            //Voting & QA
            VotingQAViewController *votingQAViewController = [[VotingQAViewController alloc] initWithNibName:@"VotingQAViewController" bundle:nil];

            self.viewControllerNotify = votingQAViewController;
        

        else if([notificationType isEqualToString:@"Survey"] || [notificationType isEqualToString:@"Quiz"])

            //Survey & Quizzes
            SurveysViewController *surveysViewController = [[SurveysViewController alloc] initWithNibName:@"SurveysViewController" bundle:nil];

            self.viewControllerNotify = surveysViewController;
        

        UINavigationController *nav=[[UINavigationController alloc]initWithRootViewController:self.viewControllerNotify];
        self.window.rootViewController = nav;
        [nav setNavigationBarHidden:YES];

    
    else
        //Normal Launch
        if(screenBounds.size.height == 568) //iPhone5
            splashViewController = [[SplashViewController alloc] initWithNibName:@"SplashViewController_5" bundle:nil];
        
        else
            splashViewController = [[SplashViewController alloc] initWithNibName:@"SplashViewController" bundle:nil];
        

        UINavigationController *nav=[[UINavigationController alloc]initWithRootViewController:splashViewController];
        self.window.rootViewController = nav;
        [nav setNavigationBarHidden:YES];

    

    [self.window makeKeyAndVisible];
    return YES;


- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo

    NSDictionary *aps = (NSDictionary *)[userInfo objectForKey:@"aps"];
    int badge = [[aps objectForKey:@"badge"] intValue];
    NSMutableString *notificationType = [aps objectForKey:@"type"];

    NSLog(@"Number of badge is = %d", badge);
    NSLog(@"notification type is = %@", notificationType);

    //For redirect to the view
    if([notificationType isEqualToString:@"Notify"])

        //Notify updates
        UpdatesViewController *uvc1 = [[UpdatesViewController alloc] initWithNibName:@"UpdatesViewController" bundle:nil];
        self.viewControllerNotify = uvc1;
    

    else if([notificationType isEqualToString:@"Voting"] || [notificationType isEqualToString:@"QA"])

        //Voting & QA
        VotingQAViewController *votingQAViewController = [[VotingQAViewController alloc] initWithNibName:@"VotingQAViewController" bundle:nil];

        self.viewControllerNotify = votingQAViewController;
    

    else if([notificationType isEqualToString:@"Survey"] || [notificationType isEqualToString:@"Quiz"])

        //Survey & Quizzes
        SurveysViewController *surveysViewController = [[SurveysViewController alloc] initWithNibName:@"SurveysViewController" bundle:nil];

        self.viewControllerNotify = surveysViewController;
    

    [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
    [[UIApplication sharedApplication] cancelAllLocalNotifications];

    UINavigationController *nav=[[UINavigationController alloc]initWithRootViewController:self.viewControllerNotify];
    self.window.rootViewController = nav;
    [nav setNavigationBarHidden:YES];
    [self.window makeKeyAndVisible];

我的问题是:这是在收到推送通知时重定向到视图控制器的正确方法吗?

使用上面的代码,它在前台和后台模式下成功地代表通知类型(通知有效负载 json 的自定义键)重定向到视图控制器类,但是重定向的视图控制器后退按钮不起作用。我不知道我在哪里做错了。如果有人知道,请帮助我。谢谢。

【问题讨论】:

你在故事板中使用的 我正在为我的应用程序中的每个视图控制器使用 XIB。 【参考方案1】:

更好您可以在didReceiveRemoteNotification 中使用NSNotificationCentre 发布通知,并在其他课程上接收通知。这样您就可以从当前视图控制器推送所需的视图控制器(无需设置为根视图控制器)。然后返回按钮将起作用。

例如

[[NSNotificationCenter defaultCenter] postNotificationName:kMesssagePushNotification object:nil userInfo:userInfo];

【讨论】:

感谢您的回复..我将如何设置 didReceiveRemoteNotification 条件以查看控制器。您是否要求从 AppDelegate 委托给其他视图控制器? 只需通过NSNotificationCentre 传递userInfo 字典并检查条件,查看我更新的答案。 @Surfer感谢您的建议,我已将导航视图控制器设为根视图,但问题又是一样的。我正在更新我的问题..请检查【参考方案2】:

后退按钮不起作用,因为您将目标视图设置为根视图。相反,您应该构建完整的导航堆栈,即通常,如果您有一个导航视图控制器作为根视图控制器,您应该首先创建它,然后构建根视图和叶视图之间的所有视图控制器。

例如,如果 MainViewController 是您的正常启动视图,并且 UpdatesViewController 的后退按钮应该指向 MainViewController,您会这样做:

MainViewController *mainVC = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];
UpdatesViewController *updatesVC = [[UpdatesViewController alloc] initWithNibName:@"UpdatesViewController" bundle:nil];

UINavigationController *navVC=[[UINavigationController alloc]initWithRootViewController:mainVC];      
[navVC setViewControllers:@[mainVC, updatesVC] animated:NO];

self.window.rootViewController = navVC;

【讨论】:

@Teemu感谢您的建议,我已将导航视图控制器设为根视图,但问题又是一样的。我正在更新我的问题..请检查 @user2786 我编辑了答案以显示您将多个视图推送到导航控制器以使后退按钮正常工作。 @Teemu我已经检查了我们编辑的代码..但没有工作。我已经尝试了很多解决方案。 你能发布确切的代码并解释你想要实现的导航结构吗? (例如,如果 UpdatesVC 打开了,它的后退按钮应该指向哪个视图?) @TeemuMy 应用程序有 1.Splash VC、2.Login VC 和 3、Main VC..收到通知后我需要重定向三个不同的 VC,即更新 VC、VotingQA VC 和调查 VC 取决于通知-类型。如果用户将在所有重定向的 VC 中点击后退按钮,那么它将来到主 VC。这就是我的应用程序的主题......我已经在我编辑的问题中向您发送了 App Delegate 的相关代码。非常感谢您给我时间..请找出我的错误,以便我可以继续...如果对我的问题有任何疑问,请随时提出。【参考方案3】:

您有两种机会访问通知数据。

    如果您在应用未启动时收到通知,则单击通知,您将在以下函数中获取通知数据:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

使用

launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]

访问通知数据并打开您期望的视图控制器。

    如果您在应用打开时收到通知,但您的应用可以在后台或前台。如果是前一种情况,你会在通知中心收到通知,点击通知后你的应用会调用如下函数:
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo

如果是后一种情况,你的应用会直接调用之前的函数。您可以使用流动代码区分它们:

UIApplicationState state = [[UIApplication sharedApplication] applicationState];
if (state == UIApplicationStateBackground || state == UIApplicationStateInactive)
    //notification is received when your app is in background
    //open the view controller you expected
else if(state == UIApplicationStateActive)
    //notification is received when your app is in foreground
    //do nothing

对不起我的台球英语,希望对你有帮助~

【讨论】:

以上是关于在 iOS 中收到 APNS 时打开视图控制器中的问题的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin/Mvvmcross:收到 iOS 推送通知时打开不同的视图控制器

当用户使用 iOS 13 Swift 5 点击推送通知时,在特定视图中打开应用程序

IOS swift - 如何在点击文本字段时打开新视图控制器后结束文本字段中的编辑

从推送通知收到的 alertView 打开应用程序后冻结

iOS:使用多个相同的视图控制器处理多个 uilocalnotification

ios 应用更新后未收到 Firebase/APNS 通知