Open Specific View from Notification

Discussion in 'iOS Programming' started by RagingGoat, Mar 21, 2013.

  1. RagingGoat macrumors 6502

    Joined:
    Jun 21, 2010
    #1
    I'm using Urban Airship for my push notifications. I'm wanting to open a particular view when the user opens the app by tapping the notification or when the user opens the app from the app icon and there are notifications that haven't been acknowledged.

    Here is my AppDelegate:

    Code:
    #import "KFBAppDelegate.h"
    #import "KFBViewController.h"
    #import "AboutUs.h"
    #import "ContactUs.h"
    #import "KYFB.h"
    #import "KFBNavControllerViewController.h"
    #import "KFBTabBarViewController.h"
    #import "RSFM.h"
    #import "LegislatorInfo.h"
    #import "Events.h"
    #import "ActionAlertsViewController.h"
    #import "UAirship.h"
    #import "UAPush.h"
    #import "UAAnalytics.h"
    
    @implementation KFBAppDelegate
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        // This prevents the UA Library from registering with UIApplcation by default when
        // registerForRemoteNotifications is called. This will allow you to prompt your
        // users at a later time. This gives your app the opportunity to explain the benefits
        // of push or allows users to turn it on explicitly in a settings screen.
        // If you just want everyone to immediately be prompted for push, you can
        // leave this line out.
        // [UAPush setDefaultPushEnabledValue:NO];
        
        //Create Airship options dictionary and add the required UIApplication launchOptions
        NSMutableDictionary *takeOffOptions = [NSMutableDictionary dictionary];
        [takeOffOptions setValue:launchOptions forKey:UAirshipTakeOffOptionsLaunchOptionsKey];
        
        // Call takeOff (which creates the UAirship singleton), passing in the launch options so the
        // library can properly record when the app is launched from a push notification. This call is
        // required.
        //
        // Populate AirshipConfig.plist with your app's info from https://go.urbanairship.com
        [UAirship takeOff:takeOffOptions];
        
        // Set the icon badge to zero on startup (optional)
        [[UAPush shared] resetBadge];
        
        // Register for remote notfications with the UA Library. This call is required.
        [[UAPush shared] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
                                                             UIRemoteNotificationTypeSound |
                                                             UIRemoteNotificationTypeAlert)];
        
        // Handle any incoming incoming push notifications.
        // This will invoke `handleBackgroundNotification` on your UAPushNotificationDelegate.
        [[UAPush shared] handleNotification:[launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey]
                           applicationState:application.applicationState];
        
        // self.tabBarController = [[UITabBarController alloc] initWithNibName:@"KFBViewController" bundle:nil];
        KFBViewController *rootView = [[KFBViewController alloc] initWithNibName:@"KFBViewController" bundle:nil];
        KFBNavControllerViewController *navController = [[KFBNavControllerViewController alloc] initWithRootViewController:rootView];
        navController.delegate = rootView;
        UIViewController *aboutUs = [[AboutUs alloc] initWithNibName:@"AboutUs" bundle:nil];
        
        KFBNavControllerViewController *navController1 = [[KFBNavControllerViewController alloc] initWithRootViewController:aboutUs];
        
        UIViewController *contactUs = [[ContactUs alloc] initWithNibName:@"ContactUs" bundle:nil];
        KFBNavControllerViewController *navController2 = [[KFBNavControllerViewController alloc] initWithRootViewController:contactUs];
        UIViewController *kyfb = [[KYFB alloc] initWithNibName:@"KYFB" bundle:nil];
        
        KFBNavControllerViewController *navController3 = [[KFBNavControllerViewController alloc] initWithRootViewController:kyfb];
        
        // UIViewController *rsfm = [[RSFM alloc] initWithNibName:@"RSFM" bundle:nil];
        // KFBNavControllerViewController *navController4 = [[KFBNavControllerViewController alloc] initWithRootViewController:rsfm];
        
        // UIViewController *li = [[LegislatorInfo alloc] initWithNibName:@"LegislatorInfo" bundle:nil];
        // KFBNavControllerViewController *navController5 = [[KFBNavControllerViewController alloc] initWithRootViewController:li];
        
        // UIViewController *events = [[Events alloc] initWithNibName:@"Events" bundle:nil];
        // KFBNavControllerViewController *navController6 = [[KFBNavControllerViewController alloc] initWithRootViewController:events];
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        
        //self.viewController = [[KFBViewController alloc] initWithNibName:@"KFBViewController" bundle:nil];
        //self.window.rootViewController = self.viewController;
        self.tabBarController = [[KFBTabBarViewController alloc] init];
        self.tabBarController.viewControllers = @[navController, navController1, navController2, navController3];
        // self.tabBarController.customizableViewControllers = nil;
        
        self.window.rootViewController = self.tabBarController;
        self.window.backgroundColor = [UIColor whiteColor];
        [self.window makeKeyAndVisible];
        
        // If application is launched due to  notification,present another view controller.
        /* UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
        
        if (notification)
        {
            ActionAlertsViewController *viewController = [[ActionAlertsViewController alloc]initWithNibName:NSStringFromClass([ActionAlertsViewController class]) bundle:nil];
            [self.window.rootViewController presentViewController:viewController animated:NO completion:nil];
            // [viewController release];
        } */
        
        return YES;
    }
    
    - (void)applicationWillResignActive:(UIApplication *)application
    {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }
    
    - (void)applicationDidEnterBackground:(UIApplication *)application
    {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }
    
    - (void)applicationWillEnterForeground:(UIApplication *)application
    {
        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    }
    
    - (void)applicationDidBecomeActive:(UIApplication *)application
    {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
        UA_LDEBUG(@"Application did become active.");
        
        // Set the icon badge to zero on resume (optional)
        [[UAPush shared] resetBadge];
    }
    
    - (void)applicationWillTerminate:(UIApplication *)application
    {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
        [UAirship land];
    }
    
    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
        // Updates the device token and registers the token with UA.
        [[UAPush shared] registerDeviceToken:deviceToken];
    }
    
    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *) error
    {
        UA_LERR(@"Failed To Register For Remote Notifications With Error: %@", error);
    }
    
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
    {
        
        UA_LINFO(@"Received remote notification: %@", userInfo);
        
        // Send the alert to UA so that it can be handled and tracked as a direct response. This call
        // is required.
        [[UAPush shared] handleNotification:userInfo applicationState:application.applicationState];
        
        // Optionally provide a delegate that will be used to handle notifications received while the app is running
        // [UAPush shared].delegate = your custom push delegate class conforming to the UAPushNotificationDelegate protocol
        
        // Reset the badge after a push received (optional)
        [[UAPush shared] resetBadge];
        
        /* ActionAlertsViewController *viewController = [[ActionAlertsViewController alloc]initWithNibName:NSStringFromClass([ActionAlertsViewController class]) bundle:nil];
        
        [self.window.rootViewController presentViewController:viewController animated:NO completion:nil]; */
        // [viewController release];
    }
    
    -(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
    {
        return UIInterfaceOrientationMaskAllButUpsideDown;
    }
    
    @end
    
     
  2. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #2
    Questions customarily have a question mark at the end. What's yours?
     
  3. RagingGoat thread starter macrumors 6502

    Joined:
    Jun 21, 2010
    #3
    Any hints or help on how I can do what I'm wanting to do? I'm finding a lot of questions online but mostly with storyboards, which I'm not using.
     
  4. RagingGoat thread starter macrumors 6502

    Joined:
    Jun 21, 2010
    #4
    I tried doing something like this in didFinishLaunchingWithOptions but when I tap the notification the app crashes.

    Code:
    // If application is launched due to  notification,present another view controller.
        UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
        
        if (notification)
        {
            ActionAlertsViewController *viewController = [[ActionAlertsViewController alloc]initWithNibName:NSStringFromClass([ActionAlertsViewController class]) bundle:nil];
            [self.window.rootViewController presentViewController:viewController animated:NO completion:nil];
        }
    
    And I tried putting this in didReceiveRemoteNotification but the app just opens to the normal home screen when tapping the notification.

    Code:
    ActionAlertsViewController *viewController = [[ActionAlertsViewController alloc]initWithNibName:NSStringFromClass([ActionAlertsViewController class]) bundle:nil];
        
        [self.window.rootViewController presentViewController:viewController animated:NO completion:nil];
    
     
  5. Duncan C macrumors 6502a

    Duncan C

    Joined:
    Jan 21, 2008
    Location:
    Northern Virginia
    #5
    Crashes how? What is the crash message? On what line of code?

    Post your whole didFinishLaunchingWithOptions method.
     
  6. RagingGoat thread starter macrumors 6502

    Joined:
    Jun 21, 2010
    #6
    The whole method is in my original post where I posted the entire AppDelegate.

    ----------

    When this code is in the didFinishLaunchingWithOptions method and I open the app by tapping a notification, the app starts to open then closes.

    Code:
    // If application is launched due to  notification,present another view controller.
        UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
        
        if (notification)
        {
            ActionAlertsViewController *viewController = [[ActionAlertsViewController alloc]initWithNibName:NSStringFromClass([ActionAlertsViewController class]) bundle:nil];
            [self.window.rootViewController presentViewController:viewController animated:NO completion:nil];
        }
    
     
  7. Duncan C macrumors 6502a

    Duncan C

    Joined:
    Jan 21, 2008
    Location:
    Northern Virginia
    #7

    Oh. I did not realize that using storyboards completely eliminated the need to create your root view controller and install it in the window.

    You need to learn how to use the debugger to attach to your application as it launches.

    Click in the list of schemes at the top left of your project and select "edit scheme".

    Then select the run step, make sure the build configuration is set to debug, and switch the launch option from "automatically" to "Wait for xxx.app to launch" (where xxx is the name of your app)

    Now, when you select run from the project menu, instead of running the app, it will say "Waiting for "xxx" to launch. If you then tap a notification, it should launch your application and attach the debugger before continuing. Thus you can set breakpoints and see why it's crashing.
     
  8. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #8
    This seems interesting:
    Code:
    ActionAlertsViewController *viewController =
        [[ActionAlertsViewController alloc]
            initWithNibName:[B]NSStringFromClass([ActionAlertsViewController class])[/B]
            bundle:nil];
    What advantage does that have over?:
    Code:
    ActionAlertsViewController *viewController =
        [[ActionAlertsViewController alloc]
            initWithNibName:@"ActionAlertsViewController"
            bundle:nil];
    or even?:
    Code:
    ActionAlertsViewController *viewController =
        [[ActionAlertsViewController alloc] init];
     
  9. RagingGoat, Mar 25, 2013
    Last edited: Mar 25, 2013

    RagingGoat thread starter macrumors 6502

    Joined:
    Jun 21, 2010
    #9
    I've figured out why it was crashing and it sort of works. Now my problem is that even though it brings up the correct view controller when opening from a notification, the navigation bar and tab bar are not there and when you select a row in the table view it does not go to the web view like it should.

    Here is how I'm trying to do this in my didFinishLaunchingWithOptions method:
    Code:
    UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
        
        if (notification)
        {
            ActionAlertsViewController *actionAlerts = [[ActionAlertsViewController alloc]initWithStyle:UITableViewStylePlain];
            WebViewController *wvc = [[WebViewController alloc]init];
            [actionAlerts setWebViewController:wvc];
            actionAlerts.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
            [self.navigationController pushViewController:actionAlerts animated:YES];
            [self.window.rootViewController presentViewController:actionAlerts animated:NO completion:nil];
        }
    
     
  10. RagingGoat thread starter macrumors 6502

    Joined:
    Jun 21, 2010
    #10
    So, I've gotten almost everything working. The web views work now when selecting a row and the navigation bar is there and seemingly works as it should. The only trouble I'm having now is getting the tab bar to show up. Here is the chunk of code I'm currently using.

    Code:
    UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
        
        if (notification)
        {  
            ActionAlertsViewController *actionAlerts = [[ActionAlertsViewController alloc] initWithStyle:UITableViewStylePlain];
            WebViewController *wvc = [[WebViewController alloc]init];
            [actionAlerts setWebViewController:wvc];
            KFBNavControllerViewController *navController7 = [[KFBNavControllerViewController alloc] initWithRootViewController:actionAlerts];
            [self.window.rootViewController presentViewController:navController7 animated:NO completion:nil];
        }
    
     
  11. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #11
    Also, is there a reason why you are subclassing UINavigationController and UITabBarController?
     

Share This Page