Swift - Instantiating a Navigation Controller Without Storyboards in App Delegate

Swift – Instantiating a navigation controller without storyboards in App Delegate

In Swift 3

Place this code inside didFinishLaunchingWithOptions method in AppDelegate class.

window = UIWindow(frame: UIScreen.main.bounds)
let mainController = MainViewController() as UIViewController
let navigationController = UINavigationController(rootViewController: mainController)
navigationController.navigationBar.isTranslucent = false
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()

How to create ViewControllers without storyboard and set one as delegate of the other one?

Note: My previous answer was using Storyboard. But since the questioner didn't want to use storyboard, I replace my answer without using storyboard.
[ this answer was inspired by https://stackoverflow.com/a/41095757/3549695 ]

First, delete the Main.storyboard. Then in Project -> Deployment Info -> Main Interface (pick LaunchScreen instead of 'Main')Sample Image

Then on AppDelegate.swift modify didFinishLaunching with the following:

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

window = UIWindow(frame: UIScreen.main.bounds)
let discoverVC = DiscoverVC() as UIViewController
let navigationController = UINavigationController(rootViewController: discoverVC)
navigationController.navigationBar.isTranslucent = false
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()

return true
}

The DiscoverVC.swift looks like this:

import UIKit

class DiscoverVC: UIViewController, SetLocationDelegate {

var name = ""

// to instantiate LocationVC once only for testing
var notVisted = true

override func viewDidLoad() {
super.viewDidLoad()

self.view.backgroundColor = .yellow
loadLocationVCOnlyOnce()
}

func loadLocationVCOnlyOnce() {
// only visit one
guard notVisted else { return }

let locationVC = LocationVC()
locationVC.delegate = self
self.navigationController?.pushViewController(locationVC, animated: true)

}

func getLocation(loc: String) {
self.name = loc
print(name)
}
}

And the LocationVC looks like this:

import UIKit

protocol SetLocationDelegate: class {
func getLocation(loc: String)
}

class LocationVC: UIViewController {

weak var delegate: SetLocationDelegate?

override func viewDidLoad() {
super.viewDidLoad()

self.view.backgroundColor = .cyan
self.delegate?.getLocation(loc: "Sam")

}

}

When you start it will automatically move from DiscoverVC (yellow background) to LocationVC (cyan background).

Then after you click the 'Back' button on top, you will see the 'Sam' printed in your console. And your view returned to DiscoverVC (yellow background).

push ViewController without storyboard

Inside AppDelegate's didFinishLaunchingWithOptions do

let fir = FirstVC()
self.window?.rootViewController = UINavigationController(rootViewController: fir)

Then this

self.navigationController?.pushViewController(vc, animated: true)

should work

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
}

Swift - Instantiate View Controller in AppDelegate

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
if Auth.auth().currentUser == nil {
let storybaord = UIStoryboard(name: "Main", bundle: Bundle.main)
let authVC = storybaord.instantiateViewController(withIdentifier: "StartVC")

window?.rootViewController?= authVC

window?.makeKeyAndVisible()
}
return true
}

I’ve used this code and it’s working for me . Try and let me know if more help needed.

How to instantiate a view controller programatically, without storyboard

The problem with doing this is that NONE of the UI for your view controller is created. What you are doing is simply instantiating an instance of the class. None of the corresponding UI is created, also your IBOutlets will be nil.

You have 2 options, either you use Interface builder and instantiate from the Nib or Storyboard, or you create ALL your UI manually in code.

For the sake of resuability you could create a static method on CNContactPickerViewController to handle the storyboard instantiation for you. See the following:

class CBContactPickerViewController: UIViewController {

static func fromStoryboard() -> CNContactPickerViewController {
return UIStoryboard(name: "foobar", bundle: nil).instantiateViewController(identifier: "CNContactPickerViewController") as! CNContactPickerViewController
}
}

You can then utilise this as follows:

self.present(viewController: CNContactPickerViewController.fromStoryboard(), animated: true, completion: nil)

navigation controller that i create programmatically not appearing as in examples

If you are using Xcode 11 and iOS 13, you need to write same code in SceneDelegate.swift. The main reason for Apple to add UISceneDelegate to iOS 13 was to create a good entry point for multi-windowed applications.

If you do not intend to support multiple windows, you can remove SceneDelegate.swift file remove UIApplicationSceneManifest key from Info.plist and remove func application(_: configurationForConnecting:, options:) and func application(_:, didDiscardSceneSessions:) methods from AppDelegate.swift

Learn more about Scene Delegate on donnywalls - Understanding the iOS 13 Scene Delegate

Xcode & Swift - unable to instantiate another view controller from AppDelegate

For iOS 13+ you need to give the instantiateViewController(withIdentifier:) in SceneDelegate, like this:

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

var window: UIWindow?

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

if UserDefaultsVault.shared.getDidFinishIntro() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
window?.rootViewController = storyboard.instantiateViewController(withIdentifier: "mainPage")
}
}
}

Note: Your code would work for devices using iOS 13 below.

starting ios project without storyboard

OK, at last i got it.

What i had to do is just add again

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

After this, just delete the .h, .m and .xib and create them again.

For any reason its working fine now.



Related Topics



Leave a reply



Submit