Opening view controller from app delegate using swift

IosSwiftUiviewcontrollerAppdelegate

Ios Problem Overview


I am trying to create a push notification which determines which view to open according to information obtained from the push.

I have managed to get the information from the push, but I am now struggling to get the view to open

Looking at other stack overflow questions I have the following currently:

App Delegate Did finish loading:

     //Extract the notification data
    if let notificationPayload = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? NSDictionary {
        // Get which page to open
        let viewload = notificationPayload["view"] as? NSString
        let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
        //Load correct view
        if viewload == "circles" {
            
            var viewController = self.window?.rootViewController?.storyboard?.instantiateViewControllerWithIdentifier("Circles") as! UIViewController
            self.window?.rootViewController = viewController
            
                        }
    }

Currently this is failing on the var ViewController = self... line.

Ios Solutions


Solution 1 - Ios

You have to set ViewController StoryBoardId property as below image.

enter image description here

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

Solution 2 - Ios

Swift 3:

This is my preferred approach when presenting a new viewController from the current viewController through the AppDelegate. This way you don't have to completely tear down your view hierarchy when handling a push notification or universal link

if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "someController") as? SomeController {
    if let window = self.window, let rootViewController = window.rootViewController {
        var currentController = rootViewController
        while let presentedController = currentController.presentedViewController {
            currentController = presentedController
        }
        currentController.present(controller, animated: true, completion: nil)
    }
}

Solution 3 - Ios

Swift 3

To present the view together with the navigation controller:

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier :"InboxViewController") as! InboxViewController
let navController = UINavigationController.init(rootViewController: viewController)
                                    
   if let window = self.window, let rootViewController = window.rootViewController {
       var currentController = rootViewController
       while let presentedController = currentController.presentedViewController {
           currentController = presentedController
        }
           currentController.present(navController, animated: true, completion: nil)
   }

Solution 4 - Ios

First Initialize the window

self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let storyBoard = UIStoryboard(name: "Main", bundle: nil)

For setting rootViewController inside AppDelegate Class

let viewController = storyBoard.instantiateViewControllerWithIdentifier("Circles") as UIViewController
self.window?.rootViewController = viewController
self.window?.makeKeyAndVisible()


Solution 5 - Ios

There is a swift 4 version

func application(_ application: UIApplication, 
didFinishLaunchingWithOptions launchOptions: 
[UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewControlleripad : UIViewController = mainStoryboardIpad.instantiateViewController(withIdentifier: "Circles") as UIViewController
            self.window = UIWindow(frame: UIScreen.main.bounds)
            self.window?.rootViewController = initialViewControlleripad
            self.window?.makeKeyAndVisible()

return true}

Solution 6 - Ios

In Swift 3

        let mainStoryboard : UIStoryboard = UIStoryboard(name: StorybordName, bundle: nil)
        let initialViewControlleripad : UIViewController = mainStoryboard.instantiateViewController(withIdentifier: identifierName) as UIViewController
        if let navigationController = self.window?.rootViewController as? UINavigationController
        {
            navigationController.pushViewController(initialViewControlleripad, animated: animation)
        }
        else
        {
            print("Navigation Controller not Found")
        }

Solution 7 - Ios

I'd say creating UIWindow each time you want to change rootViewController is bad idea. After couple changes of rootVC (using upper solution) you are gonna have many UIWindows in your app at one time.

In my opinion better solution is:

  1. Get new rootVC: let rootVC = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateViewControllerWithIdentifier("newRootVCIdentifier") as UIViewController
  2. Set frame for new rootVC from UIScreen's bounds: rootVC.view.frame = UIScreen.mainScreen().bounds
  3. Set new root controller for current window (here with animation): UIView.transitionWithView(self.window!, duration: 0.5, options: .TransitionCrossDissolve, animations: { self.window!.rootViewController = rootVC }, completion: nil)

Done!

You don't need method window?.makeKeyAndVisible(), cause this solution works on current app window.

Solution 8 - Ios

Swift 3 SWRevealViewController

    self.window = UIWindow(frame: UIScreen.main.bounds)
    let storyBoard = UIStoryboard(name: "Main", bundle: nil)
    
    let viewController = storyBoard.instantiateViewController(withIdentifier: "SWRevealViewController") as! SWRevealViewController
    self.window?.rootViewController = viewController
    self.window?.makeKeyAndVisible()

Solution 9 - Ios

let storyboard = UIStoryboard(name: "Main", bundle: nil)
    
    let destinationViewController = storyboard.instantiateViewController(withIdentifier: "LandVC") as! LandingPageVC
    
    destinationViewController.webpageURL = NotificationAdvertisement._htmlpackagePath
    destinationViewController.adID = NotificationAdvertisement._adID
    destinationViewController.toneID = NotificationAdvertisement.toneID
   
    let navigationController = self.window?.rootViewController as! UIViewController
   
    navigationController.showDetailViewController(destinationViewController, sender: Any?.self)

Solution 10 - Ios

SWIFT 4

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

    let destinationViewController = storyboard.instantiateViewController(withIdentifier: "LandVC") as! LandingPageVC

    destinationViewController.webpageURL = NotificationAdvertisement._htmlpackagePath
    destinationViewController.adID = NotificationAdvertisement._adID
    destinationViewController.toneID = NotificationAdvertisement.toneID

    let navigationController = self.window?.rootViewController as! UIViewController

    navigationController.showDetailViewController(destinationViewController, sender: Any?.self)

Solution 11 - Ios

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let windowScene = (scene as? UIWindowScene) else { return }
    self.window = UIWindow(windowScene: windowScene)

    let mainStoryboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    let vc : UIViewController = mainStoryboard.instantiateViewController(withIdentifier: "LoginViewController")
    let rootNC = UINavigationController(rootViewController: vc)
    self.window?.rootViewController = rootNC
    self.window?.makeKeyAndVisible()

}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionListerView Question on Stackoverflow
Solution 1 - IosKirit ModiView Answer on Stackoverflow
Solution 2 - IosQuy BuiView Answer on Stackoverflow
Solution 3 - IosArvin Sanmuga RajahView Answer on Stackoverflow
Solution 4 - IosiDhavalView Answer on Stackoverflow
Solution 5 - Ios未来陆家嘴顶尖的投资人View Answer on Stackoverflow
Solution 6 - IosAmul4608View Answer on Stackoverflow
Solution 7 - IosMarcin BilińskiView Answer on Stackoverflow
Solution 8 - IosAnilView Answer on Stackoverflow
Solution 9 - Iosharsh shahView Answer on Stackoverflow
Solution 10 - IosSachin RasaneView Answer on Stackoverflow
Solution 11 - IosRajesh Kumar SahilView Answer on Stackoverflow