Push Notification -didFinishLaunchingWithOptions

24,806

Solution 1

Since you only want to present a viewController when you get a Push Notification, you may try utilizing NSNotificationCenter for your purposes:

Part 1: Set up a class (in your case, the rootViewController) to listen/respond to a NSNotification

Suppose, MainMenuViewController is the rootViewController of your navigationController.
Set up this class to listen to a NSNotification:

- (void)viewDidLoad {
    //...
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(presentMyViewOnPushNotification)
                                                 name:@"HAS_PUSH_NOTIFICATION"
                                               object:nil];
}

-(void)presentMyViewOnPushNotification {
    //The following code is no longer in AppDelegate
    //it should be in the rootViewController class (or wherever you want)

    UIStoryboard *mainstoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    PushMessagesVc *pvc = [mainstoryboard instantiateViewControllerWithIdentifier:@"PushMessagesVc"];

    [self presentViewController:pvc animated:YES completion:nil];
    //either presentViewController (above) or pushViewController (below)
    //[self.navigationController pushViewController:pvc animated:YES];
}

Part 2: Post Notification (possible from anywhere in your code)

In your case, AppDelegate.m methods should look like:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //firstly, don't sleep the thread, it's pointless
    //sleep(1); //remove this line

    if (launchOptions) { //launchOptions is not nil
        NSDictionary *userInfo = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
        NSDictionary *apsInfo = [userInfo objectForKey:@"aps"];

        if (apsInfo) { //apsInfo is not nil
            [self performSelector:@selector(postNotificationToPresentPushMessagesVC) 
                       withObject:nil
                       afterDelay:1];
        }
    }
    return YES;
}

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    //this method can be done using the notification as well
    [self postNotificationToPresentPushMessagesVC];
}

-(void)postNotificationToPresentPushMessagesVC {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"HAS_PUSH_NOTIFICATION" object:nil];
}

PS: I haven't done this for my projects (yet) but it works and is the best way i could think of doing this kinda stuff (for the moment)

Solution 2

Swift 5

To get push notification Dictionary in didFinishLaunchingWithOptions when app is kill and push notification receive and user click on that

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    if let userInfo = launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification] as? [String: AnyObject] {
        if let aps1 = userInfo["aps"] as? NSDictionary {
            print(aps1)
        }
    }
    return true
}

Push notification Dictionary will display in alert.

Solution 3

Swift 2.0 For 'Not Running' State (Local & Remote Notification)

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {


// Handle notification
if (launchOptions != nil) {

    // For local Notification
    if let localNotificationInfo = launchOptions?[UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification {

        if let something = localNotificationInfo.userInfo!["yourKey"] as? String {

            self.window!.rootViewController = UINavigationController(rootViewController: YourController(yourMember: something))
        }


    } else

    // For remote Notification
    if let remoteNotification = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as! [NSObject : AnyObject]? {

        if let something = remoteNotification["yourKey"] as? String {
            self.window!.rootViewController = UINavigationController(rootViewController: YourController(yourMember: something))
        }
    }

}


return true

}

Solution 4

Swift 5

I write my notification to var "notification" in didFinishLaunchingWithOptions, and if "notification" != nil started my push in applicationDidBecomeActive, after that removed him ( = nil)

class AppDelegate: UIResponder, UIApplicationDelegate {

var notification: [AnyHashable : Any]? = nil

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    registerForPushNotifications()

    //write notification to var
    if launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification] != nil {
        self.notification = launchOptions![UIApplication.LaunchOptionsKey.remoteNotification] as? [AnyHashable : Any]
    }

    return true
}

func applicationDidBecomeActive(_ application: UIApplication) {
    if notification != nil {
    //for launch notification after terminate app
        NotificationCenter.default.post(name: Notification.Name(rawValue: "startPush"), object: nil)
        notification = nil
    }
}
Share:
24,806
cdsoft
Author by

cdsoft

Updated on July 10, 2022

Comments

  • cdsoft
    cdsoft almost 2 years

    When I send a push notification and my app is open or in the background and I click on the push notification, my application redirects to PushMessagesVc viewController (as intended)

    I use the code as below for this:

    -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
        UIStoryboard *mainstoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
        PushMessagesVc *pvc = [mainstoryboard instantiateViewControllerWithIdentifier:@"PushMessagesVc"];
    
        [self.window.rootViewController presentViewController:pvc
                                                     animated:YES
                                                   completion:NULL];
    }
    

    There is no problem in the code/scenario above but if the application is closed and I click on a push notification, the application does not redirect my PushMessagesVc viewController in this case & the application stays on the main screen.

    For the 2nd scenario, I use the following code:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        sleep(1);
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeNone)];
        [UIApplication sharedApplication].applicationIconBadgeNumber = 1;
    
        NSDictionary *userInfo = [launchOptions valueForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"];
        NSDictionary *apsInfo = [userInfo objectForKey:@"aps"];
    
        if(apsInfo) {
            UIStoryboard *mainstoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
            PushMessagesVc* pvc = [mainstoryboard instantiateViewControllerWithIdentifier:@"PushMessagesVc"];
            [self.window.rootViewController presentViewController:pvc animated:YES completion:NULL];
            return YES;
        }
        return YES;
    }
    

    But in this case, the PushMessagesVc does not appear.