2

When the app is in terminate state and I receive a push notification. Which if I view I want the app to load normally but it should present a viewController over the rootViewController for which I've added a close button and whenever i will tap this button i want simply dismiss this viewController.

In the method which is called when I open the app from notification I've done this:

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
    let tabBarController = self.window!.rootViewController as! UITabBarController
    self.window?.rootViewController = tabBarController
    let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    apptVC = storyboard.instantiateViewController(withIdentifier: "NotificationVC") as! NotificationsViewController
    window?.makeKeyAndVisible()
    window?.rootViewController?.present(apptVC, animated: true, completion: nil)
completionHandler()
    }
}

But unfortunately when I do that the app crashes. I've implemented push notification using firebase. I want the app to run normally like it does it's just like presenting a view controller over the root view controller on launch when user is coming from notification.

UPDATE
here is the screenshot of my storyboard: enter image description here

Chaudhry Talha
  • 7,231
  • 11
  • 67
  • 116
  • 1
    An error message from the crash would be helpful. Your storyboard and `makeKeyAndVisible` code shouldn't appear here. If anywhere it should be in `didFinishLaunching`. You only need the last line of code in this function. – Joe Oct 25 '17 at 05:58
  • @Joe I've added the code as you suggested but it's still the same and how can I print the error as the app is in terminate state and there is no way the xCode can print the error as it is not running from there. – Chaudhry Talha Oct 25 '17 at 06:38
  • @ChaudhryTalha This is completely wrong! You'll need a delegate method only not the launch options – Mannopson Oct 25 '17 at 06:39
  • @Mannopson not sure what you mean there. Can you provide a code sample in the answer. – Chaudhry Talha Oct 25 '17 at 06:43
  • Here the what I meant! If you want to present a view controller when the notification is tapped? You'll need a `didReceive` method which is the delegate method of `UNUserNotificationDelegate`. – Mannopson Oct 25 '17 at 06:46

2 Answers2

4

So you'll need to insatiate tab bar controller first:

let storyboard = UIStoryboard.init(name: "YourStoryboardName", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "YourTabBarController") as! UITabBarController

And insatiate all of the UINavigationControllers with the your desired view controller:

let firstNavigationController = storyboard.instantiateViewiController(withIdentifier: "YourFirstNavigationController") as! UINavigationController

let NotificationVC = storyboard.instantiateViewController(withIdentifier: "NotificationVC") as! NotificationsViewController

And make them all as viewControllers of tab bar controller:

tabBarController.viewControllers = [firstNavigationController]

Which is the navigation controller should be present this view controller? For example:

tabBarController.selectedViewController == firstNavigationController {
    firstNavigationController.present(NotificationVC, animated: true, completion: nil)
}

It's a last thing:

self.window = UIWindow.init(frame: UIScreen.main.bounds)
self.window?.rootViewController = tabBarController
self.window?.makeKeyAndVisible()

Note It's just recommendation and therefore I have used one UNavigationController

So I have created a function called present().

func present() {

let storyboard = UIStoryboard.init(name: "YourStoryboardName", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "YourTabBarController") as! UITabBarController
let firstNavigationController = storyboard.instantiateViewiController(withIdentifier: "YourFirstNavigationController") as! UINavigationController
let NotificationVC = storyboard.instantiateViewController(withIdentifier: "NotificationVC") as! NotificationsViewController

tabBarController.viewControllers = [firstNavigationController]

tabBarController.selectedViewController == firstNavigationController {
        firstNavigationController.present(NotificationVC, animated: true, completion: nil)
 }

self.window = UIWindow.init(frame: UIScreen.main.bounds)   
self.window?.rootViewController = tabBarController
self.window?.makeKeyAndVisible()


    }
}

But it's not useful even I think this is useless. We'll need an action whenever notification is tapped. And we should check an action identifier like this:

extension AppDelegate: UNUserNotificationCenterDelegate {

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

        switch response.actionIdentifier {
        case UNNotificationDefaultActionIdentifier:
            self.present()
            completionHandler()

        default:
            break;
        }
    }
}

Hope it helps

Mannopson
  • 2,634
  • 1
  • 16
  • 32
1

Maybe your rootView Controller is nil. Try setting a rootview_Controller before presenting class even though you may have specified a rootviewController in did finish launnch of appDelegate.

  func userNotificationCenter(_ center: UNUserNotificationCenter,
                                    didReceive response: UNNotificationResponse,
                                    withCompletionHandler completionHandler: @escaping () -> Void) {
 viewController = storyboard.instantiateViewControllerWithIdentifier("YourRootVC") as UIViewController
 self.window?.rootViewController = viewController

 window?.rootViewController?.present(yourPusHNotificationVC, animated: true, completion: nil)
    completionHandler()
        }
    }
Jeesson_7
  • 761
  • 1
  • 11
  • 38