0

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.

John Doe
  • 277
  • 3
  • 14

2 Answers2

1

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)
MarkHim
  • 5,686
  • 5
  • 32
  • 64
  • Thank you for your help! Now the print statement will be called, but how do I instantiate a VC in order to have it as part of my navigation controller in my Tab Bar Controller? – John Doe Oct 06 '16 at 14:51
  • assuming your rootViewController is a TabbarController, then simply do sth like `let myViewController = MyViewController()` then sth like ((self.window.rootViewController as? UITabbarController)?.selectedViewController as? UINavigationController)?.pushViewController(myViewController, animated: true)` -- Can't really answer with code too well in a question – MarkHim Oct 06 '16 at 15:02
  • Thank you so much! That work's perfectly! Have a nice day! – John Doe Oct 06 '16 at 15:13
0

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.

NavodaP
  • 218
  • 3
  • 18
Hot'n'Young
  • 491
  • 4
  • 12