Lister
Lister

Reputation: 1118

Opening view controller from app delegate using swift

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.

Upvotes: 81

Views: 115925

Answers (11)

Rajesh Kumar Sahil
Rajesh Kumar Sahil

Reputation: 39

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()

}

Upvotes: -1

Kirit Modi
Kirit Modi

Reputation: 23407

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

Upvotes: 119

Amul4608
Amul4608

Reputation: 1448

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")
        }

Upvotes: 5

Sachin Rasane
Sachin Rasane

Reputation: 1559

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)

Upvotes: 0

sixsixsix
sixsixsix

Reputation: 1868

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}

Upvotes: 6

harsh shah
harsh shah

Reputation: 31

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)

Upvotes: 1

Anil
Anil

Reputation: 272

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()

Upvotes: 3

iDhaval
iDhaval

Reputation: 3205

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()

Upvotes: 8

Arvin Sanmuga Rajah
Arvin Sanmuga Rajah

Reputation: 520

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)
   }

Upvotes: 14

Marcin Biliński
Marcin Biliński

Reputation: 31

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.

Upvotes: 3

Quy Bui
Quy Bui

Reputation: 689

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)
    }
}

Upvotes: 56

Related Questions