John Doe
John Doe

Reputation: 277

How to go directly to a specific View Controller if Notification has been opened

I have an UITabBarController which presents in one tab a table of chats. If the user clicks on one row, a view controller will be displayed that presents the latest messages.

Now I am introducing Push notifications. The desired behavior would be to automatically go to the chat room if the user opens up the Push notification. Although there's plenty information available on how to handle these use cases, I do not succeed in implementing it.

Here's my code so far:

   func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        if (!isUserLoggedIn()) {
            // show login vc
        } else {
            let protectedController = mainStoryboard.instantiateViewController(withIdentifier: "TabBarController") as! UITabBarController

            if let notificationPayload = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? NSDictionary {
                if let chatId = notificationPayload["chatId"] as? String {
                    print(chatId)
                    // show chat VC
                }
            }

            window!.rootViewController = protectedController
            window!.makeKeyAndVisible()
        }


        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options: [.alert, .sound]) { (granted, error) in
            // Enable or disable features based on authorization.
        }
        application.registerForRemoteNotifications()

        return true
    }

The print statement will never be called but that may be due to the fact that the application is completely closed before opening the notification.

Upvotes: 0

Views: 4100

Answers (2)

Hot'n'Young
Hot'n'Young

Reputation: 491

When the user taps on a notification, callback method of the app delegate is:

application:didReceiveRemoteNotification:fetchCompletionHandler:

More information about notifications from Apple.

You should put your code inside this method.

Also you can create Router class (subclass of NSObject), which will show chat view controller and will be responsible for navigation between view controllers in application.

It's a good manner incapsulate this logic into separate class, not keeping it in the AppDelegate class.

Upvotes: 0

MarkHim
MarkHim

Reputation: 5766

didFinishLaunchingWithOptions is not necessarily called, when you click on a notification, only if your app is not in the memory anymore

In your willFinishLaunchingWithOptions function of your appDelegate, set up a delegate for the currentNotificationCenter

func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
    UNUserNotificationCenter.current().delegate = self
}

Make sure your AppDelegate implements UNUserNotificationCenterDelegate relevant for you could be this

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    let userInfo = response.notification.request.content.userInfo
    if let chatID = userInfo["chatID"] as? String {
        // here you can instantiate / select the viewController and present it
    }
    completionHandler()
}

Update to answer your follow-up question: How to add a UIViewController to a UINavigationController within your UITabbarController

In order to instantiate your ViewController and add it to your UITabbarController:

let myViewController = MyViewController() 
guard let tabbarController = self.window.rootViewController as? UITabbarController else {
    // your rootViewController is no UITabbarController
    return
}
guard let selectedNavigationController = tabbarController.selectedViewController as? UINavigationController else {
    // the selected viewController in your tabbarController is no navigationController!
    return
}
selectedNavigationController.pushViewController(myViewController, animated: true)

Upvotes: 1

Related Questions