How To Start An iOS App Without Storyboards With Screenshots

Storyboards can be great for simple applications. However, they can quickly become a problem in larger projects and team environments.

For Xcode 11 and up

How to start an iOS app without storyboards on Xcode 11 and up:

  1. Delete your Main.storyboard in your project navigator.
  2. Update your SceneDelegate with your new view controller.
  3. Go to Deployment Info and delete the Main text.
  4. Search Xcode for Main and delete it from Info.plist.

Your scene delegate code should look like this:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let windowScene = (scene as? UIWindowScene) else { return }
    window = UIWindow(frame: windowScene.coordinateSpace.bounds)
    window?.windowScene = windowScene
    let navigationVC = UINavigationController()
    window?.rootViewController = navigationVC
    navigationVC.pushViewController(ViewController(), animated: false)
    window?.makeKeyAndVisible()
}

Starting An App In Xcode 11 With Screenshots

Delete your Main.storyboard file:

how to start an ios app without storyboards 2020 03 08 20 29 52

Update your scene delegate code:

import UIKit

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(frame: windowScene.coordinateSpace.bounds)
        window?.windowScene = windowScene
        let navigationVC = UINavigationController()
        window?.rootViewController = navigationVC
        navigationVC.pushViewController(ViewController(), animated: false)
        window?.makeKeyAndVisible()
    }

}

Go to Deployment Info and delete the Main text:

how to start an ios app without storyboards 2020 03 08 20 32 23

Search Xcode for Main and delete it from Info.plist:

how to start an ios app without storyboards 2020 03 08 20 35 10

Now you can run your app without storyboards!

You can double check everything is working by opening up your ViewController.swift file and adding a background color in viewDidLoad():

import UIKit

class ViewController: UIViewController {

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

Your simulator or iPhone should look like this:

how to start an ios app without storyboards 2020 03 08 20 37 39

Why should you not use Storyboards

Storyboards fail at runtimes instead of compile time. This can lead to a crash which is a terrible user experience. This often happens when you named something incorrectly in the Storyboard. If you wrote it in code, it the compiler would catch it before the app is built.

Storyboards become confusing very quickly when the application is more complex. As the app gets more and more screens, navigating the storyboard is a painful process. You will have to often zoom in and out, pan left and right just to understand the logic of your application. Especially if multiple people are working on the app, the logic of the screens can quickly become impossible to follow.

Merge conflicts will become a regular problem in team settings. Since you only have one storyboard file that everybody modifies when adding new screens, this is bound to have many merge conflicts. The merge conflicts are also difficult to resolve since you’ll have to parse through machine-generated code that Xcode created. This adds a large overhead to iOS projects when there are two or more developers involved.

Reusable screens and code is also another reason to avoid using storyboards. You have to set the styles for each element in a storyboard. If you worked in code, you could create a class that has all the common styles that you use repeatedly.

You lose flexibility when you choose to use a storyboard. In the beginning, it may seem like you are saving time. However, when you want a custom animation or a special transition for certain screens, you will often find yourself regretting the decision to use the storyboard. You will have to figure out workarounds that would’ve been otherwise quite simple to do in code.

Refactoring is difficult with storyboards since you’ll only find out certain bugs at runtime! When you refactor using the Xcode tools, it may not rename those elements in the storyboard. The compiler will not be able to catch these bugs and it will result in a crash to the end user. Not good!

Should I use the interface builder and XIB files

XIB files are great option. I love using XIB files because Apple’s auto layout is great for getting user interfaces to work on different screens. Having a separate XIB file for each view controller gives you a lot of the advantages of using storyboards with none of the cons.

This also helps with the decoupling of view controllers. This makes it easy for you to display the view controller anywhere in your application.

Here’s how to create an isolated view controller with its own XIB:

Right click in your Project Navigator and select New File…

zero to app store

Select Cocoa Touch Class in the dialog that pops up:

zero to app store

Name your class. Make sure it’s a subclass of UIViewController and check the box that says Also create XIB file.

zero to app store

Go ahead and click next. You now have a ViewController with it’s own XIB file.

zero to app store

You can open up that .XIB file in the interface builder and do as you please! Such as adding a background color like so.

zero to app store

How do I push new view controllers without Storyboards

Now that your view controllers are separate from your storyboard file, you may be wondering how to push these view controllers without using storyboards. Don’t worry – the process is actually quite simple in code.

Let’s take a look at an example here where the blue view controller pushes a red view controller onto the screen. In this example, we start our application with a navigation view controller that has a view controller called BlueViewController pushed onto it. So our didFinishLaunchingWithOptions in AppDelegate.swift looks like this:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    window = UIWindow(frame: UIScreen.main.bounds)
    let navgiationController = UINavigationController()
    let blueViewController = BlueViewController()
    navgiationController.pushViewController(blueViewController, animated: false)
    window!.rootViewController = navgiationController
    window!.makeKeyAndVisible()
    return true
}

BlueViewController has a single button that pushes a new view controller onto the screen. Here’s the code for our BlueViewController.swift:

import UIKit

class BlueViewController: UIViewController {

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

    @IBAction func clicked(_ sender: Any) {
        let redViewController = UIViewController()
        redViewController.view.backgroundColor = UIColor.red
        navigationController?.pushViewController(redViewController, animated: true)
    }
}

The IBAction function clicked is connected to a button through the interface builder.

zero to app store

Should I use pure code or XIBs files

This is ultimately a personal preference. Some developers prefer to work only in code. I prefer using XIB files as it makes developing user interfaces a lot faster. The interface builder in Xcode has improved greatly over the years and the ability to preview the UI speeds up development greatly.

The con of using XIBs is that if two developers work on the same view. This can quickly lead to merge conflicts in a hard to read XIB file. I’ve resolved some of these conflicts before, but they are a pain to do.

Ideally developers would be working on different views. For example developer 1 would work on FirstViewController.swift and FirstViewController.xib. Developer 2 would work on SecondViewController.swift and SecondViewController.xib. This prevents having to resolve messy merge conflicts.

There are some software engineers that are extremely proficient at building UI’s in code. This is a viable strategy, especially if you’re very experienced. However I believe it is harder to learn how layout elements in code than it is in the interface builder. Manually setting constraints can be difficult for the beginner iOS developer.

I recommend newbies start with XIB files in interface builder and slowly write some parts of their user interface in code. This hybrid approach is a good way to determine the best strategy for your product and team.

What is Auto Layout? Auto Layout is user interface system that allows developers to build interfaces using sets of constraints and rules. It allows these user interfaces to dynamically change based on screen size.

What is a .XIB file? XIB stands for XML Interface Builder. These files are generated by Xcode’s Interface Builder and contain the user interface.

For Xcode 10 or earlier

How to start an iOS app without storyboards:

  1. Delete your Main.storyboard in your project navigator
  2. Click on the project file in the project navigator. Find in your target’s options General > Deployment and look for the Main Interface. Clear this field.
  3. Open up AppDelegate.swift find the didFinishLaunchingWithOptions function. Create a UIWindow.
  4. Create a new UIViewController in the same function.
  5. Set the root view controller of your created UIWindow to your new UIViewController.
  6. Call makeKeyAndVisible on the UIWindow.

Xcode 10 or earlier pictures

When you’ve created a new project, you’ll see the Main.storyboard in your project navigator. This can be found in the left panel of your Xcode project. Right click on this file and a menu will appear. Select Delete.

zero to app store

Once that’s done, you should select the Project File in the Project Navigator which will open the project’s settings. In the pictured example, the project is named testing2.

zero to app store

Select the General tab and find the Deployment Info section. There will be a field here that is labelled Main Interface.

zero to app store

Clear the Main Interface field so it is blank.

zero to app store

Now open up the AppDelegate.swift file from the project navigator and find the didFinishLaunchingWithOptions function.

zero to app store

Modify your didFinishLaunchingWithOptions to this:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
 window = UIWindow(frame: UIScreen.main.bounds)
 let mainViewController = UIViewController()
 mainViewController.view.backgroundColor = UIColor.blue
 window!.rootViewController = mainViewController
 window!.makeKeyAndVisible()
    return true
}

The first line creates a new UIWindow. We then create a new UIViewController and set its background color. Set the window to our new view controller and make that window key and visible. When you run your application you should see the following blue screen:

zero to app store

If you liked this post and want to learn more, check out The Complete iOS Developer Bootcamp. Speed up your learning curve - hundreds of students have already joined. Thanks for reading!

Eddy Chung

I teach iOS development on ZeroToAppStore.com.

Similar Posts