1
votes

I have an app that uses XIB and not Storyboard. The rootViewController is a TabBarController. There are 5 tabs, and each tab contains a NavigationController. What I would like to do, is have the app PUSH a certain view controller whenever the user taps on a received Push Notification. In my didFinishLaunchingWithOptions I have (amongst other setup things):

 window.rootViewController = self.tabBarController;
    [window makeKeyAndVisible];

In later code:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    [PFPush handlePush:userInfo];
    if (application.applicationState == UIApplicationStateInactive) {
        [self handleRemoteNotificationWithPayload:userInfo];
    }
}
-(void)handleRemoteNotificationWithPayload:(NSDictionary *)payload {
   NSLog(@"User tapped notification");
    NewsViewController *dvController8 = [[NewsViewController alloc] initWithNibName:@"NewsViewController" bundle:[NSBundle mainBundle]];
        [self.tabBarController.navigationController pushViewController:dvController8 animated:YES];


}

However, nothing at all happens when I tap the notification, though the NSLog does fire in the console. Suggestions?

BASED off an answer, I now have

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    [PFPush handlePush:userInfo];
    UINavigationController *nav = (UINavigationController *) self.tabBarController.selectedViewController;
    NewsViewController *dvController8 = [[NewsViewController alloc] initWithNibName:@"NewsViewController" bundle:[NSBundle mainBundle]];
    [nav pushViewController:dvController8 animated:YES];

}

But this only works if the app is already running suspended in background. If it has crashed or user has forced it close from app switcher, it will just open the app, and not push the controller.

EDIT:

Here is the didFinishLaunchingWithOptions method:

UIUserNotificationType userNotificationTypes = (UIUserNotificationTypeAlert |
                                                    UIUserNotificationTypeBadge |
                                                    UIUserNotificationTypeSound);



    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:userNotificationTypes
                                                                             categories:nil];

    [[UIApplication sharedApplication]
     registerUserNotificationSettings:settings];
    [application registerUserNotificationSettings:settings];
    [application registerForRemoteNotifications];
1

1 Answers

3
votes

If every tab on your tab controller is a navigation controller try this:

UINavigationController *nav = (UINavigationController *) self.tabBarController.selectedViewController;
NewsViewController *dvController8 = [[NewsViewController alloc] initWithNibName:@"NewsViewController" bundle:[NSBundle mainBundle]];
[nav pushViewController:dvController8 animated:YES];

So basically first get the reference of the selected controller, and make a pushViewController over the selected view controller.

EDIT, how to handle if the app is not running in background:

if the application is not running in background you have to do it on application:didFinishLaunchingWithOptions

The documentation says: "if the app is not running when a remote 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 remote notification. Instead, your implementation of the application:willFinishLaunchingWithOptions: or application:didFinishLaunchingWithOptions: method needs to get the remote notification payload data and respond appropriately."

Please check: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/#//apple_ref/occ/intfm/UIApplicationDelegate/application:didReceiveRemoteNotification:

So my suggestion is first create a helper method to handle your notification, something like this:

- (void)handleNotification:(NSDictionary *)userInfo {
    UINavigationController *nav = (UINavigationController *) self.tabBarController.selectedViewController;
    NewsViewController *dvController8 = [[NewsViewController alloc] initWithNibName:@"NewsViewController" bundle:[NSBundle mainBundle]];
    [nav pushViewController:dvController8 animated:YES];
}

From now every-time you have to handle a remote notification you just need to call handleNotification method.

Second change your didReceiveRemoteNotification implementation to something like:

[self handleNotification:userInfo];

Finally add the following to your didFinishLaunchingWithOptions implementation:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // your code here


    if ([launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]) {
        // this means we received a remote notification
        [self handleNotification:(NSDictionary *) [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]];
    }

    return YES;
}

So on the didFinishLaunchingWithOptions method you check if the launchOptions dictionary has some object assigned for UIApplicationLaunchOptionsRemoteNotificationKey. If it does, that means the app was opened from a remote notification. The value assigned to that key is the payload of the notification.

Note: I didn't test the code on xcode so may have some typos, but you should get the idea of how can you achieve what you need.

Hope it helps!