108

Creating a new project in XCode 6 doesn't allow to disable Storyboards. You can only select Swift or Objective-C and to use or not Core Data.

I tried deleting the storyboard and from the project removing the main storyboard and manually setting the window from didFinishLaunching

In the AppDelegate I have this:

class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow
var testNavigationController: UINavigationController

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {

        testNavigationController = UINavigationController()
        var testViewController: UIViewController = UIViewController()
        self.testNavigationController.pushViewController(testViewController, animated: false)

        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)

        self.window.rootViewController = testNavigationController

        self.window.backgroundColor = UIColor.whiteColor()

        self.window.makeKeyAndVisible()

        return true
    }
}

However, XCode gives me an error:

Class 'AppDelegate' has no initializers

Anyone has succeed in this?

EhTd
  • 3,260
  • 4
  • 19
  • 18
  • 1
    Possible duplicate of [How to create an Empty Application in Xcode 6 without Storyboard](http://stackoverflow.com/questions/25783282/how-to-create-an-empty-application-in-xcode-6-without-storyboard) – S1LENT WARRIOR Apr 25 '16 at 10:31

13 Answers13

91

All it takes for not using Storyboards for the rootViewController:

1· Change AppDelegate.swift to:

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
        window = UIWindow(frame: UIScreen.main.bounds)
        if let window = window {
            window.backgroundColor = UIColor.white
            window.rootViewController = ViewController()
            window.makeKeyAndVisible()
        }
        return true
    }
}

2· Create a ViewController subclass of UIViewController:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.blue
    }
}

3· If you created the project from an Xcode template:

  1. Remove the key-value pair for key "Main storyboard file base name" from Info.plist.
  2. Delete the storyboard file Main.storyboard.

As you can see in the first code snippet, instead of implicitly unwrapping an optional, I rather like the if let syntax for unwrapping the optional window property. Here I'm using it like if let a = a { } so that the optional a becomes a non-optional reference inside the if-statement with the same name – a.

Finally self. is not necessary when referencing the window property inside it own class.

Kalle Kabell
  • 218
  • 1
  • 8
tobiasdm
  • 9,688
  • 1
  • 18
  • 15
  • 1
    Why the `if let window = window {`? I figured it out! It's so you don't need to use `window!` every time. – Bilal Akil Oct 19 '14 at 00:21
  • @2unco I'm glad you figured it out. This is described in the last part of my answer about `if let a = a {}`. – tobiasdm Oct 20 '14 at 12:56
  • I would move the call to `makeKeyAndVisible()` to be _after_ setting `rootViewController`. Otherwise you'll get a warning about how the window is expected to have a root view controller at the end of application launch. – Sebastien Martin Dec 27 '14 at 18:09
  • `if let a = a { }` looks weird. Are you sure it's OK to use the same variable name for the non-optional reference? Apple always uses different names in their Swift docs. Also, why is this better than just using `window!` every time? – ma11hew28 Apr 24 '15 at 22:34
  • 1. `if let a = a { }` is perfectly fine. You can use `if let anA = a { }` if it makes you feel more comfortable. 2. `window!` is a runtime check since you a explicitly unwrapping an optional. I like the compile time checks that Swift provides us, so why not use it. – tobiasdm Apr 30 '15 at 13:33
  • Thanks, m8! Starting up with Swift today so everything is kind of strange (: – Felipe Oct 27 '15 at 18:14
  • This makes a black 1px line appear on top and bottom of the ViewControllers. Any clues on how to get rid of it? (Not using `Launch.storyboard` file – jdev Mar 11 '17 at 10:47
  • @jdev That does not sound related to this answer. – tobiasdm Mar 13 '17 at 13:08
  • @duemunk: Sorry, I thought it was... If I completely remove storyboards from my template project (including Launch.storyboard), then I can see a 1px line at the top and bottom of the screen. I didn´t know why, and it seemed related to the absence of Storyboards, because if I create a new storyboard and set it as `Launch Screen File` the lines go away, so I thought I could ask. As it was a requirement to not use Storyboard, after removing them, I added a white LaunchImage (in all needed resolutions) to the xcassets, and the black lines went away.. – jdev Mar 13 '17 at 13:16
71

You must mark the window and testNavigationController variables as optional:

var window : UIWindow?
var testNavigationController : UINavigationController?

Swift classes require non-optional properties to be initialized during the instantiation:

Classes and structures must set all of their stored properties to an appropriate initial value by the time an instance of that class or structure is created. Stored properties cannot be left in an indeterminate state.

Properties of optional type are automatically initialized with a value of nil, indicating that the property is deliberately intended to have “no value yet” during initialization.

When using optional variables, remember to unwrap them with !, such as:

self.window!.backgroundColor = UIColor.whiteColor();
Community
  • 1
  • 1
akashivskyy
  • 44,342
  • 16
  • 106
  • 116
  • 1
    Everything makes perfect sense in your answer, until the end. will you please explain that last part?? unwrap? is this required? – DanMoore Sep 10 '14 at 05:43
  • 1
    You cannot store a non-optional property in your `AppDelegate` (unless it has a value during initialization, or it is lazily resolved). If you store an optional property and you're **sure** that it's not `nil`, you "unwrap it from its optionality" using `!` operator. – akashivskyy Sep 10 '14 at 06:44
  • what is the best practice , self.window! or using if let window = .. ? – Sai Prasanna Feb 20 '15 at 05:56
  • 1
    If you are sure that your window exists (and you can be sure in this particular case), you can go with `!`. – akashivskyy Feb 20 '15 at 06:09
  • so does this mean when we use storyboards, the backgroundColor it somehow defaulted to `.white`? – mfaani Nov 27 '17 at 23:19
13

If you want to Initialize your viewController with xib and and need to use navigation controller. Here is a piece of code.

var window: UIWindow?
var navController:UINavigationController?
var viewController:ViewController?

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

    viewController = ViewController(nibName: "ViewController", bundle: nil);
    navController = UINavigationController(rootViewController: viewController!);

    window?.rootViewController = navController;
    window?.makeKeyAndVisible()

    return true
}
Prince Kumar Sharma
  • 12,591
  • 4
  • 59
  • 90
6

Try the following code:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
    self.window!.backgroundColor = UIColor.whiteColor()

    // Create a nav/vc pair using the custom ViewController class

    let nav = UINavigationController()
    let vc = NextViewController ( nibName:"NextViewController", bundle: nil)

    // Push the vc onto the nav
    nav.pushViewController(vc, animated: false)

    // Set the window’s root view controller
    self.window!.rootViewController = nav

    // Present the window
    self.window!.makeKeyAndVisible()
    return true

}
PREMKUMAR
  • 8,283
  • 8
  • 28
  • 51
2

I have found the answer it had nothing to do with the xcode setup, removing storyboard and the reference from project is the right thing. It had to do with the swift syntax.

The code is the following:

class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?
var testNavigationController: UINavigationController?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {

        self.testNavigationController = UINavigationController()
        var testViewController: UIViewController? = UIViewController()
        testViewController!.view.backgroundColor = UIColor.redColor()
        self.testNavigationController!.pushViewController(testViewController, animated: false)

        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)

        self.window!.rootViewController = testNavigationController

        self.window!.backgroundColor = UIColor.whiteColor()
        self.window!.makeKeyAndVisible()

        return true
    }

}
EhTd
  • 3,260
  • 4
  • 19
  • 18
2

You can just do it like this:

class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    var IndexNavigationController: UINavigationController?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
        var IndexViewContoller : IndexViewController? = IndexViewController()
        self.IndexNavigationController = UINavigationController(rootViewController:IndexViewContoller)
        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        self.window!.rootViewController = self.IndexNavigationController
        self.window!.backgroundColor = UIColor.whiteColor()
        self.window!.makeKeyAndVisible()
        return true
    }
}
Hilen
  • 761
  • 7
  • 8
2

Updated for Swift 3.0:

window = UIWindow()
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
2

Update: Swift 5 and iOS 13:

  1. Create a Single View Application.
  2. Delete Main.storyboard (right-click and delete).
  3. Delete Storyboard Name from the default scene configuration in the Info.plist file: enter image description here
  4. Open SceneDelegate.swift and change func scene from:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
    guard let _ = (scene as? UIWindowScene) else { return }
}

to

 func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).x

    if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = ViewController()
        self.window = window
        window.makeKeyAndVisible()
    }
}
Jogendra Kumar
  • 894
  • 11
  • 16
1

I recommend you use controller and xib

MyViewController.swift and MyViewController.xib

(You can create through File->New->File->Cocoa Touch Class and set "also create XIB file" true, sub class of UIViewController)

class MyViewController: UIViewController {
   .....    
}

and In AppDelegate.swift func application write the following code

....
var controller: MyViewController = MyViewController(nibName:"MyViewController",bundle:nil)
self.window!.rootViewController = controller
return true

It should be work!

Yi Feng Xie
  • 4,378
  • 1
  • 26
  • 29
  • I tried the same way you mentioned but error: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: – shripad20 Jul 31 '14 at 16:26
1

Here is a complete swift test example for an UINavigationController

        import UIKit
        @UIApplicationMain
        class KSZAppDelegate: UIResponder, UIApplicationDelegate {    
          var window: UIWindow?
          var testNavigationController: UINavigationController?

          func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            // Override point for customization after application launch.        
            // Working WITHOUT Storyboard
            // see http://randexdev.com/2014/07/uicollectionview/
            // see http://stackoverflow.com/questions/24046898/how-do-i-create-a-new-swift-project-without-using-storyboards
            window = UIWindow(frame: UIScreen.mainScreen().bounds)
            if let win = window {
              win.opaque = true    
            //you could create the navigation controller in the applicationDidFinishLaunching: method of your application delegate.    
              var testViewController: UIViewController = UIViewController()
              testNavigationController = UINavigationController(rootViewController: testViewController)
              win.rootViewController = testNavigationController
              win.backgroundColor = UIColor.whiteColor()
              win.makeKeyAndVisible()
// see corresponding Obj-C in https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/NavigationControllers.html#//apple_ref/doc/uid/TP40011313-CH2-SW1
        //      - (void)applicationDidFinishLaunching:(UIApplication *)application {
        //    UIViewController *myViewController = [[MyViewController alloc] init];
        //    navigationController = [[UINavigationController alloc]
        //                                initWithRootViewController:myViewController];
        //    window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        //    window.rootViewController = navigationController;
        //    [window makeKeyAndVisible];
            //}
            }
            return true
          }
    }
Dmitry Konovalov
  • 508
  • 7
  • 16
0

Why don't you just create an empty application? the storyboard is not created to me...

allemattio
  • 1,836
  • 17
  • 33
0

We can create navigation-based application without storyboard in Xcode 6 (iOS 8) like as follows:

  • Create an empty application by selecting the project language as Swift.

  • Add new cocoa touch class files with the interface xib. (eg. TestViewController)

  • In the swift we have only one file interact with the xib i.e. *.swift file, there is no .h and .m files.

  • We can connect the controls of xib with swift file same as in iOS 7.

Following are some snippets for work with the controls and Swift

//
//  TestViewController.swift
//

import UIKit

class TestViewController: UIViewController {

    @IBOutlet var testBtn : UIButton

    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        // Custom initialization
    }

    @IBAction func testActionOnBtn(sender : UIButton) {
        let cancelButtonTitle = NSLocalizedString("OK", comment: "")

        let alertController = UIAlertController(title: "Title", message: "Message", preferredStyle: .Alert)

        // Create the action.
        let cancelAction = UIAlertAction(title: cancelButtonTitle, style: .Cancel) { action in
            NSLog("The simple alert's cancel action occured.")
        }

        // Add the action.
        alertController.addAction(cancelAction)

        presentViewController(alertController, animated: true, completion: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

Changes in AppDelegate.swift file

//
//  AppDelegate.swift
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    var navigationController: UINavigationController?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        self.window!.backgroundColor = UIColor.whiteColor()
        self.window!.makeKeyAndVisible()

        var testController: TestViewController? = TestViewController(nibName: "TestViewController", bundle: nil)
        self.navigationController = UINavigationController(rootViewController: testController)
        self.window!.rootViewController = self.navigationController

        return true
    }

    func applicationWillResignActive(application: UIApplication) {
}

    func applicationDidEnterBackground(application: UIApplication) {
    }

    func applicationWillEnterForeground(application: UIApplication) {
    }

    func applicationDidBecomeActive(application: UIApplication) {
    }

    func applicationWillTerminate(application: UIApplication) {
    }

}

Find code sample and other information on http://ashishkakkad.wordpress.com/2014/06/16/create-a-application-in-xcode-6-ios-8-without-storyborard-in-swift-language-and-work-with-controls/

Ashish Kakkad
  • 23,586
  • 12
  • 103
  • 136
0

In iOS 13 and above when you create new project without storyboard use below steps:

  1. Create project using Xcode 11 or above
  2. Delete storyboard nib and class
  3. Add new new file with xib
  4. Need to set root view as UINavigationController SceneDelegate
  5. add below code:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
    // guard let _ = (scene as? UIWindowScene) else { return }
    
    if let windowScene = scene as? UIWindowScene {
        self.window = UIWindow(windowScene: windowScene)
        let mainController = HomeViewController() as HomeViewController
        let navigationController = UINavigationController(rootViewController: mainController)
        self.window!.rootViewController = navigationController
        self.window!.makeKeyAndVisible()
    }
}
Bram
  • 2,718
  • 1
  • 22
  • 43
Yogesh shelke
  • 438
  • 4
  • 12