How to make your push notification Open a certain view controller?
Asked Answered
R

4

6

I looked on SO but I wasn't able to find any question that discusses when you receive a push notification how can you then open a specific view controller. For example if you are creating an app like WhatsApp and you receive two different push notifications ie messages from two different users how would you direct from the app delegate to the respective viewController?

As far as I know in the userinfo dictionary that the appDelegate gives you you can give an ID to a specific viewController but I don't know how to give any a tribute to a specific view controller so that then you could again direct to that viewController. Kindly include a code snippet with your answer

**** Swift or Objective-C answers are both acceptable ****

Raynaraynah answered 10/6, 2016 at 16:27 Comment(0)
B
15

You can detect if the app opened from the notification with this code in app delegate. You will need to set the initial view controller when the application state is UIApplicationStateInactive before the app has become active. You can perform any logic there to decide which view controller should be opened and what content should be shown in that view controller.

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{

    if(application.applicationState == UIApplicationStateActive) {

        //app is currently active, can update badges count here

    } else if(application.applicationState == UIApplicationStateBackground){

        //app is in background, if content-available key of your notification is set to 1, poll to your backend to retrieve data and update your interface here

    } else if(application.applicationState == UIApplicationStateInactive){

        //app is transitioning from background to foreground (user taps notification), do what you need when user taps here

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

        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];

        UIViewController *viewController = // determine the initial view controller here and instantiate it with [storyboard instantiateViewControllerWithIdentifier:<storyboard id>];

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

    }

}
Bakunin answered 10/6, 2016 at 19:12 Comment(4)
Thank you so much. The third id statement is where you are actually going from background to foreground...the first 2 are only updating the model without any UI interaction. right?. So basically you link through the identifier of the viewController correct?Raynaraynah
Sorry I took a couple days to comment, that is correct.Bakunin
is it a good idea to reassign your self.window.rootViewController? Isn't it better to just look at say your tabBar and then assign the correct selectedIndex? I mean if you have a memory leak there and then reassign your tab bar, that entire object will likely stay in memory...Raynaraynah
@Honey yeah you are right, but I think even if you did have a memory leak and navigated to the correct selectedIndex you still would need to address the memory leak at some point. p.s. I like how you commented two years later :)Bakunin
D
4

Here is the Swift 3 Version with switch/case instead of if/else

    open func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
    switch application.applicationState {
    case .active:
        print("do stuff in case App is active")
    case .background:
        print("do stuff in case App is in background")
    case .inactive:
        print("do stuff in case App is inactive")
    }
}
Donielle answered 4/5, 2017 at 10:39 Comment(0)
I
0
//This method is called when user tap on the notification

      func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

           print("user clicked on the notification")
           let userInfo = response.notification.request.content.userInfo

           print(userInfo)

           //check your response and navigate to specific view controller
           moveToNextViewController()
      }

     func moveToNextViewController() {
    //Add code for present or push view controller
           let vc = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier:"ViewController") as! ViewController                    
          self.navigationController?.pushViewController(vc, animated: true)
    }
Inkwell answered 6/9, 2019 at 10:42 Comment(0)
E
0

This method is called when user tap on the notification. implement in appdelegate

var navigationC: UINavigationController?

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

    if USERDEFAULT.value(forKey: "isLogin") != nil  {
        let tabbarvc = MainStoryboard.instantiateViewController(withIdentifier: "TabBarVC") as! TabBarVC
        self.navigationC = UINavigationController(rootViewController: tabbarvc)
    }else {
        let loginvc = MainStoryboard.instantiateViewController(withIdentifier: "LoginVC") as! LoginVC
        self.navigationC = UINavigationController(rootViewController: loginvc)
    }

    self.navigationC?.setNavigationBarHidden(true, animated: false)
    self.window?.clipsToBounds = true
    self.window?.rootViewController = navigationC
    self.window?.makeKeyAndVisible()

    return true
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
    print("-------------\nUser info in notification -> \(userInfo)\n-------------")
    let dict = userInfo["aps"] as? NSDictionary ?? [:]
    if USERDEFAULT.value(forKey:"isLogin") != nil{
        let type = dict["type"] as? Int ?? 0
        switch type {
        case 0:
            break
        case 1:
            for vc in self.navigationC!.viewControllers {
                if vc is TabBarVc {
                    let  exam = dict["exam"] as? String ?? ""
                    if exam == ""{
                        let TestVC = MainStoryboard.instantiateViewController(withIdentifier: "TestVC") as! TestVC
                        TestVC.chapterId = dict["chapter_id"] as? String ?? ""
                        TestVC.strSubTitle = dict["chapter"] as? String ?? ""
                        self.navigationC?.isNavigationBarHidden = true
                        self.navigationC?.pushViewController(TestVC, animated: true)
                    }else if exam != ""{
                        let ExamTestVC = MainStoryboard.instantiateViewController(withIdentifier: "ExamTestVC") as! ExamTestVC
                        ExamTestVC.examId = dict["exam_id"] as? String ?? ""
                        ExamTestVC.strSubTitle = dict["exam"] as? String ?? ""
                        self.navigationC?.isNavigationBarHidden = true
                        self.navigationC?.pushViewController(ExamTestVC, animated: true)
                    }
                    return;
                }
            }
            break

        case 2:
            for vc in self.navigationC!.viewControllers {
                if vc is TabBarVc {
                    let VideoListVC = MainStoryboard.instantiateViewController(withIdentifier: "VideoListVC") as! VideoListVC
                    VideoListVC.chapterId = dict["chapter_id"] as? String ?? ""
                    VideoListVC.video_id = dict["video_id"] as? String ?? ""
                    VideoListVC.strSubTitle = dict["chapter"] as? String ?? ""
                    VideoListVC.questionsCount = dict["question_count"] as? Int ?? 0
                    VideoListVC.testCount = dict["test_count"] as? Int ?? 0
                    self.navigationC?.isNavigationBarHidden = true
                    self.navigationC?.pushViewController(VideoListVC, animated: true)
                    return;
                }
            }
            break

        case 3:

            break

        default: break

        }
    }else{
        let loginVC = SignupiPadStoryboard.instantiateViewController(withIdentifier: "LoginVC") as! LoginVC
        SignupStoryboard = SignupiPadStoryboard
        self.navigationC = UINavigationController(rootViewController: loginVC)
    }

}

OR you can direct open view controller like whatsapp chat..etc.

@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
{
    let userInfo = notification.request.content.userInfo
    let dictAps = userInfo["aps"] as! NSDictionary
    print(dictAps)
    let notification_type = dictAps["notification_type"] as? Int ?? 0
    if notification_type == 6{
        if isChatActive == false{
            completionHandler([.alert, .badge, .sound])
        }else{
            if USERDEFAULT.value(forKey:"isLogin") != nil{
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ReloadChatMessages"), object: nil, userInfo: (dictAps as! [AnyHashable : Any]))
            }else{
                completionHandler([.alert, .badge, .sound])
            }
        }
    }else{
        completionHandler([.alert, .badge, .sound])
    }

}
Electret answered 30/10, 2019 at 12:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.