mandem112
mandem112

Reputation: 191

How to check in AppDelegate if a particular ViewController is currently open

I am trying to prevent a push notification show on the app home screen when a certain userMessagesViewController is currently open. I don't want users receiving a push notification if this specific viewController is open. My function that sends the push notification is in the appDelegate. How can I check. Here is my implementation so far.

  let messagesVC = UserMessageViewController()

    if messagesVC.view.window != nil {
        print("Messages viewcontroller is visible and open")
        } else {
        print("Messages viewcontroller isnt visible and not open")
    }

Upvotes: 1

Views: 1553

Answers (2)

Callam
Callam

Reputation: 11539

By initiating messagesVC, you're creating a brand new UserMessageViewController that won't have been presented yet. The particular instance of the controller you want will already be instantiated, so you must find it using the view controller hierarchy.

The AppDelegate gives you access to the rootViewController of your application which will be the very first controller you have in your storyboard. From this controller, you can make your way through the child view controllers in search of a UserMessageViewController.

Here is an extension that will start at the rootViewController and bubble its way up until it reaches the top of the view controller hierarchy stack.

extension UIApplication {
    func topViewController(_ base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        switch (base) {
        case let controller as UINavigationController:
            return topViewController(controller.visibleViewController)
        case let controller as UITabBarController:
            return controller.selectedViewController.flatMap { topViewController($0) } ?? base
        default:
            return base?.presentedViewController.flatMap { topViewController($0) } ?? base
        }
    }
}

Create a new file called UIApplication+TopViewController.swift and paste in the above extension. Then inside AppDelegate, you will be able to get the current view controller that is being presented using UIApplication.shared.topViewController():

if let messagesVC = UIApplication.shared.topViewController() as? UserMessageViewController {
    print("Messages viewcontroller is visible and open")
} else {
    print("Messages viewcontroller isnt visible and not open")
}

By casting the top view controller to UserMessageViewController, we can determine whether or not the notification should be presented.

Upvotes: 2

Woodstock
Woodstock

Reputation: 22926

This should work for you:

if messagesVC.viewIfLoaded?.window != nil {
    // viewController is visible, handle notification silently.
}

Your appDelegate will have a reference to the VC. It should probably be a property of the delegate.

Upvotes: 0

Related Questions