74

I've been trying to redo the work on my app programmatically. (Without the use of storyboards)

I'm almost done, except making the navigation controller manually.

Currently, I only have 1 viewcontroller. And of course the appDelegate

The navigation Controller, will be used throughout all pages in the application.

If anyone could help me out, or send a link to some proper documentation for doing this programmatically it would be greatly appreciated.

EDIT:

I forgot to mention it's in Swift.

4
  • 1
    possible duplicate of Programatically creating UINavigationController in iOS Commented Mar 2, 2015 at 7:25
  • Note that in the vast majority of cases, you can just do it on storyboard ... stackoverflow.com/a/22981726/294884 You can then turn off the whacky button bar, and it's "just as good" as doing it programmatically. Commented Jan 2, 2018 at 19:28
  • 1
    @ThomasKilian How is this a duplication? The other one is objective C but this is Swift?? Commented Sep 28, 2018 at 11:13
  • 1
    @user3390652 see the edit history. When the OP asked it was not tagged with Swift. Commented Sep 28, 2018 at 12:10

7 Answers 7

115

In AppDelegate.swift

Swift 1, 2:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
   self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
   var nav1 = UINavigationController()
   var mainView = ViewController(nibName: nil, bundle: nil) //ViewController = Name of your controller
   nav1.viewControllers = [mainView]
   self.window!.rootViewController = nav1
   self.window?.makeKeyAndVisible()
}

Swift 4+: and Swift 5+

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
   self.window = UIWindow(frame: UIScreen.main.bounds)
   let nav1 = UINavigationController()
   let mainView = ViewController(nibName: nil, bundle: nil) //ViewController = Name of your controller
   nav1.viewControllers = [mainView]
   self.window!.rootViewController = nav1
   self.window?.makeKeyAndVisible()
}
Sign up to request clarification or add additional context in comments.

7 Comments

Nevermind I realized where I went wrong. Changed it back to mainView and did "var mainView = NameOfYourViewController()" And it worked. Thank you so much for the help!
What if i want to add it to a view already has uitabbarcontroller?
@TomSawyer , Before adding controller on tabbar , create UINavigationController object using your controller and use that navigation object for add on UITabbarcontroller
You can also use the UINavigationController(rootViewController: _) initializer instead of assigning an array with one element to the viewControllers property. But that is just to save one line of code :)
This seems wrong to me (although I know it works, I have used it). the self.window.rootViewController is of type UIViewController, which should in Swift object to being assigned a UINavigationController.
|
22

Value of type 'AppDelegate' has no member 'window'

For those building newer projects with SceneDelegate.swift, you can use the 'var window: UIWindow?' in SceneDelegate instead of the removed 'var window' in AppDelegate

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

    window?.windowScene = windowScene
    window?.makeKeyAndVisible()

    let viewController = ViewController()
    let navViewController = UINavigationController(rootViewController: viewController)
    window?.rootViewController = navViewController
}

1 Comment

Thanks, I suppose to set naviBar in single view controller, and unable to figure out it constraint. Now I know that is wrong. It should be set in AppDelegate or SceneDelegate as global use.
17

I would recommend starting your AppDelegate with this skeleton:

1) use let wherever you can!

2) UINavigationController has the rootViewController property.

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    let viewController = ViewController(nibName: nil, bundle: nil) //ViewController = Name of your controller
    let navigationController = UINavigationController(rootViewController: viewController)

    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
    self.window?.rootViewController = navigationController
    self.window?.makeKeyAndVisible()

    return true
}

Comments

10

Here is another take in the SceneDelegate class:

var window: UIWindow?

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

    if let windowScene = scene as? UIWindowScene {

        let window = UIWindow(windowScene: windowScene)    
        let navController = UINavigationController()
        let viewController = ViewController()

        navController.viewControllers = [viewController]            
        window.rootViewController = navController
        self.window = window
        window.makeKeyAndVisible()
    }
}

2 Comments

how to make it work with tabbarcontrolle so it shows the title?
I'm not entirely sure that I know what your asking for. You would just add the UITabBarController as the rootViewController like this -> window.rootViewController = MyTabBarController()
3

Try this one . It will guide you how to use navigation controller.

Programatically creating UINavigationController in iOS

AppDelegate.h

    #import <UIKit/UIKit.h>
    #import "LoginViewController.h"

    @interface AppDelegate : UIResponder <UIApplicationDelegate>

    @property (strong, nonatomic) UIWindow *window;
    @property (strong,nonatomic) UINavigationController *navigationController;
    @property (strong,nonatomic) LoginViewController *loginVC;

    @end

AppDelegate.m

    #import "AppDelegate.h"
    #import "LoginViewController.h"

    @implementation AppDelegate

  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.

   self.loginVC = [[LoginViewController alloc]initWithNibName:nil bundle:nil];
   self.loginVC.title = @"Login Page";

   self.navigationController = [[UINavigationController alloc]initWithRootViewController:self.loginVC];

   self.window.rootViewController = self.navigationController;
   [self.window makeKeyAndVisible];
  }

Then when you want to push the other view controller , simple use following code to move to another view controller.

- (IBAction)pushMyProfileView:(id)sender
{
    self.myProfileVC = [[MyProfileViewController alloc]initWithNibName:nil bundle:nil];
    [appDelegate.navigationController pushViewController:self.myProfileVC animated:YES];
}

5 Comments

Hey, thank you so much for the reply!. I know this is completely my own fault, I only added it as a tag and forgot to mention it. But I'm coding it in swift. Unfortunately I have no idea how to translate that code to swift.
The answer should have been in swift
@UmairAfzal okay I will be post updated code for swift very soon if you have needed it.
@HardikShekhat actually I do need please reffer to my question. stackoverflow.com/questions/37606778/…
@UmairAfzal I will post answer there for swift.
0

It is probably overkill, but I find myself doing this often enough that I just extended UIViewController and created an embedInNavigationController method. So now I can just call viewController.embedInNavigationController.

extension UIViewController {

func embedInNavigationController() -> UINavigationController {
    return UINavigationController(rootViewController: self)
   }
}

Comments

-3
 self.window = UIWindow(frame: UIScreen.main.bounds) 
 let storyboard = UIStoryboard(name: "Main", bundle: nil) 
 let storyboard_Secondary = UIStoryboard(name: "Secondary", bundle: nil) 
 var initialViewController = UIViewController() 

 let aUser = CommonMethods.loadCustomObject("\(Constants.kUserProfile)") as? User  
 if aUser?.respCode == 1 { 
    initialViewController = storyboard_Secondary.instantiateViewController(withIdentifier: "MainTabVC")
    UIApplication.shared.statusBarStyle = .lightContent
    let navigationController = UINavigationController(rootViewController: initialViewController)
    navigationController.isNavigationBarHidden = true
    self.window!.rootViewController = navigationController
    self.window!.makeKeyAndVisible() 
}

1 Comment

This answer is not general, and relies on a class that is not part of the language. This answer also does not show the import of that class, nor does it say anything about where the class came from or how to get it. It is entirely possible to rewrite this without anything in CommonMethods, resulting in fewer lines of code, and a more general answer. There is additional styling code in here that is not required for the NavigationController to work properly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.