Storyboards can be great for simple applications. However, they can quickly become a problem in larger projects and team environments.
How to start an iOS app without storyboards on Xcode 11 and up:
Main.storyboard
in your project navigator.SceneDelegate
with your new view controller.Deployment Info
and delete the Main
text.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()
}
Delete your Main.storyboard
file:
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:
Search Xcode for Main
and delete it from Info.plist
:
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:
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!
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…
Select Cocoa Touch Class
in the dialog that pops up:
Name your class. Make sure it’s a subclass of UIViewController and check the box that says Also create XIB file
.
Go ahead and click next. You now have a ViewController with it’s own XIB file.
You can open up that .XIB file in the interface builder and do as you please! Such as adding a background color like so.
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.
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.
How to start an iOS app without storyboards:
Main.storyboard
in your project navigatorGeneral
> Deployment
and look for the Main Interface
. Clear this field.AppDelegate.swift
find the didFinishLaunchingWithOptions
function. Create a UIWindow.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.
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
.
Select the General
tab and find the Deployment Info
section. There will be a field here that is labelled Main Interface
.
Clear the Main Interface
field so it is blank.
Now open up the AppDelegate.swift
file from the project navigator and find the didFinishLaunchingWithOptions
function.
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:
The Complete iOS App Development Bootcamp
Disclosure: This website may contain affiliate links, meaning when you click the links and make a purchase, we receive a commission.