How to Get Visible Viewcontroller from App Delegate When Using Storyboard

How to get visible viewController from app delegate when using storyboard?

This should do it for you:

- (void)applicationWillResignActive:(UIApplication *)application
{
UIViewController *vc = [self visibleViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}

- (UIViewController *)visibleViewController:(UIViewController *)rootViewController
{
if (rootViewController.presentedViewController == nil)
{
return rootViewController;
}
if ([rootViewController.presentedViewController isKindOfClass:[UINavigationController class]])
{
UINavigationController *navigationController = (UINavigationController *)rootViewController.presentedViewController;
UIViewController *lastViewController = [[navigationController viewControllers] lastObject];

return [self visibleViewController:lastViewController];
}
if ([rootViewController.presentedViewController isKindOfClass:[UITabBarController class]])
{
UITabBarController *tabBarController = (UITabBarController *)rootViewController.presentedViewController;
UIViewController *selectedViewController = tabBarController.selectedViewController;

return [self visibleViewController:selectedViewController];
}

UIViewController *presentedViewController = (UIViewController *)rootViewController.presentedViewController;

return [self visibleViewController:presentedViewController];
}

Opening view controller from app delegate using swift

You have to set ViewController StoryBoardId property as below image.

Sample Image

open viewController using coding as below in swift

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewControlleripad : UIViewController = mainStoryboardIpad.instantiateViewControllerWithIdentifier("Circles") as UIViewController
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = initialViewControlleripad
self.window?.makeKeyAndVisible()

return true
}

For iOS 13+ (based on an article by dev2qa)

Open SceneDelegate.swift and add following

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

// If this scene's self.window is nil then set a new UIWindow object to it.
self.window = self.window ?? UIWindow()

// Set this scene's window's background color.
self.window!.backgroundColor = UIColor.red

// Create a ViewController object and set it as the scene's window's root view controller.
self.window!.rootViewController = ViewController()

// Make this scene's window be visible.
self.window!.makeKeyAndVisible()

guard scene is UIWindowScene else { return }
}

There is an open-source navigation utility which attempts to make this easier. Example

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

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.

set initial viewcontroller in appdelegate - swift

Xcode11 and SceneDelegate note:

Starting from Xcode11, because of SceneDelegates, it's likely that you shouldn't do it inside AppDelegate. Instead do it from SceneDelegate. For more on that see this other answer



Old answer:

I used this thread to help me convert the objective C to swift, and its working perfectly.

Instantiate and Present a viewController in Swift

Swift 2 code:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)

let storyboard = UIStoryboard(name: "Main", bundle: nil)

let initialViewController = storyboard.instantiateViewControllerWithIdentifier("LoginSignupVC")

self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()

return true
}

Swift 3 code:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)

let storyboard = UIStoryboard(name: "Main", bundle: nil)

let initialViewController = storyboard.instantiateViewController(withIdentifier: "LoginSignupVC")

self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()

return true
}

How to push a view controller from App Delegate on didReceiveRemoteNotification in Swift?

I managed to get it working as I needed with help from both Sh_Khan and the answer I found in this thread: How can I show ViewController in UITabBarController?

My initial view controller is a tabBar and therefore, this is the correct code for me:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

let info = userInfo as NSDictionary
let name: String = info.value(forKey: "view-controller") as! String

switch name {
case "controller1":
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let controller1VC = storyboard.instantiateViewController(withIdentifier: "controller1VC") as! Controller1VC
let tabBar = self.window?.rootViewController as? UITabBarController
let nav = tabBar?.selectedViewController as? UINavigationController
nav?.pushViewController(controller1VC, animated: true)
default:
print("Nothing")
}
}

So this code will essentially convert the tabBar to a UINavigationController allowing for a pushViewController to work.

I hope this helps anyone else.

How to set the Initial viewController in AppDelegate Programatically?

1) Open your AppDelegate.swift and add property

var window: UIWindow?

2) In

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

a) initialize this window:

window = UIWindow(frame: UIScreen.main.bounds)

b) set UIViewController you needed to window's rootViewController property:

window?.rootViewController = myViewController

c) make this window key and visible:

window?.makeKeyAndVisible()

That is all.
And don't forget to remove your storyboard from target settings:
Remove storyboard from target

Hope its help.

View controller added in app delegate not appearing

You can do it like that:

func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if Settings.appSettings.authToken != nil {
self.showMainController()
}
NotificationCenter.default.addObserver(forName: .authorizationOperationDidSuccess,
object: nil, queue: nil) { (notification) in
self.showMainController()
}

return true
}

private func showMainController() {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)

let controller: UIViewController =
storyBoard.instantiateViewController(withIdentifier: "Main") as UIViewController
if self.window == nil {
self.window = UIWindow(frame: UIScreen.main.bounds)
}
self.window?.backgroundColor = UIColor.white
self.window?.rootViewController = controller
self.window?.makeKeyAndVisible()
}

private func showAuthorizationController() {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)

let controller: UIViewController =
storyBoard.instantiateViewController(withIdentifier: "Auth") as UIViewController
if self.window == nil {
self.window = UIWindow(frame: UIScreen.main.bounds)
}
self.window?.backgroundColor = UIColor.white
self.window?.rootViewController = controller
self.window?.makeKeyAndVisible()
}

On successful login make

NotificationCenter.default.post(name: .authorizationOperationDidSuccess,
object: nil)

How to get root view controller?

if you are trying to access the rootViewController you set in your appDelegate. try this:

Objective-C

YourViewController *rootController = (YourViewController*)[[(YourAppDelegate*)
[[UIApplication sharedApplication]delegate] window] rootViewController];

Swift

let appDelegate  = UIApplication.sharedApplication().delegate as AppDelegate
let viewController = appDelegate.window!.rootViewController as YourViewController

Swift 3

let appDelegate  = UIApplication.shared.delegate as! AppDelegate
let viewController = appDelegate.window!.rootViewController as! YourViewController

Swift 4 & 4.2

let viewController = UIApplication.shared.keyWindow!.rootViewController as! YourViewController

Swift 5 & 5.1 & 5.2

let viewController = UIApplication.shared.windows.first!.rootViewController as! YourViewController


Related Topics



Leave a reply



Submit