SwiftUI versus storyboards is part of the bigger question of whether you should use a GUI to create a GUI. This has been a subject of debate since at least 1992, when Steve Jobs introduced Interface Builder.
GUI builders, such as Xcode’s Interface Builder, enable you to create by dragging and dropping GUI elements. However, most can’t design dynamic GUIs. Plus, most generate data files that aren't fit to be kept in source code control systems (e.g., Git). On the other hand, writing GUI code manually is tedious.
SwiftUI is a compromise. It requires you to manually code GUI components, but you can view the results immediately without running the app. SwiftUI’s previews provide immediate feedback like Interface Builder does without keeping XML files inside source control systems.
This post will teach you the pros and cons of using SwiftUI versus storyboards for iOS (and iPadOS) app development. By the end of the post, you'll have the knowledge you need to make an informed choice, given your situation.
How Is SwiftUI Different from Storyboard?
SwiftUI is a UI framework, whereas storyboard is a component of UIKit, another UI framework. If SwiftUI is Lego Technic, then the storyboard is the baseplate of a plain old Lego brick set, the latter being UIKit. You can mix and match SwiftUI with storyboard, as you can stick Lego Technic on top of a Lego baseplate.
SwiftUI components are created by writing Swift code, which gets compiled into machine code and linked to the application. But storyboards are created via Xcode’s Interface Builder by laying out controls on a canvas. The editor then generates an XML file, which gets translated into an application resource file. At runtime, this resource file gets read to create on-screen controls. As you might imagine, storyboards have more runtime overheads during initialization than pure SwiftUI.
Is SwiftUI Better Than Storyboard?
SwiftUI is a better choice than storyboards because it's easier to maintain and easier to test while providing a decent design-time GUI.
Better Source Control
SwiftUI is all Swift, at home in source code control systems. Handling merge conflicts on SwiftUI files is like handling any other Swift source files. However, a storyboard file is a large and complex machine-generated XML file, making merge conflicts almost nerve-wracking to resolve.
Better Multi-Platform Support
SwiftUI allows more shared UI code between iOS and macOS. But storyboard files for macOS applications target the AppKit UI framework and are separate from iOS storyboards targeting UIKit. Storyboard in macOS centers around the NSStoryboard class, whereas in iOS centers around UIStoryboard—unless you use Catalyst to build the macOS app.
But Catalyst apps come with constraints. Even Catalyst won’t help you combine UIKit with AppKit, requiring workarounds like including an AppKit plugin inside the Catalyst app.
Better Design-Time Functionality
Similar to what Interface Builder does in UIKit, SwiftUI previews show your design inside Xcode without running your app. SwiftUI goes further, allowing you to interact with your preview to try out its dynamic behaviors. But storyboards cannot. Plus, you can have multiple previews based on the same component, each preview showing different sample data. For example, you can preview the same component under different color schemes.
Technically, SwiftUI previews compile your code and run it in a restricted environment. Hence, it runs custom components as part of a preview. You can see your customization to SwiftUI code or even UIKit custom classes. However, storyboards are limited to displaying custom components as placeholders.
Better Testability
SwiftUI code can be unit-tested via XCTest without running your application. You manipulate the underlying data of a SwiftUI view and then assert elements in the resulting view hierarchy with the help of libraries like ViewInspector for SwiftUI. In contrast, testing a storyboard calls for a functional test like XCUITest; running the app under instrumentation, navigating to the location of the storyboard under test, simulating user input, and then asserting the live view hierarchy by targeting a few accessibility identifiers.
It's New but Plays Well With Peers
SwiftUI is less mature than UIKit. That said, you can bring UIKit components into SwiftUI, including storyboards.
Exceptions Where Storyboards Are Better
There are situations when storyboards are preferable. For example, you might want to use storyboards when you need rapid results and merge conflicts are non-issues. You might also need to use storyboards when you’ve reached the end of SwiftUI’s support.
You can prototype user interface flows rapidly with storyboards. You can design how multiple screens interconnect and have an overview of the possible flows in Xcode’s storyboard editor. Alas, SwiftUI previews can’t do this (yet), as it doesn't show a map of screen flows.
Another reason is to cater to edge cases solvable through storyboards but not SwiftUI. Fortunately, the storyboard is still available to help.
Does SwiftUI Replace Storyboard?
If your deployment target is iOS 14 or later, then SwiftUI can replace storyboards. This iOS release introduced the Scene protocol, SwiftUI’s equivalent of UIKit’s UIStoryboard class.
But you don't need to replace all of your storyboards with SwiftUI. There's no indication that Apple will be deprecating storyboards. Apple would likely announce deprecation a few years before removing a widely used API like storyboards.
Can You Use Storyboard With SwiftUI?
Like you can combine UIKit with SwiftUI components in an iOS app, you can also use storyboards with SwiftUI. You can embed a storyboard within a SwiftUI view hierarchy and vice-versa.
Hence, you can use this technique to develop new components in SwiftUI while keeping pre-existing code based on storyboards. Likewise, you can bring your pre-existing storyboards into a SwiftUI container.
A SwiftUI View Inside a Storyboard
Use UIHostingController to embed a SwiftUI view inside a storyboard. Place it anywhere you would use a UIViewController instance. Then, provide the UIHostingController instance with an instance of your SwiftUI view via its constructor.
For example, suppose we have a SwiftUI view SampleSwiftUIView. You could embed this inside an existing storyboard via a container view, which is a view containing another view controller. In turn, the view controller being contained is a UIHostingController.
You provide an instance of the SwiftUI view to the hosting controller via a method annotated with @IBSegueAction. The snippet below shows a sample method that instantiates a UIHostingController, which hosts a SampleSwiftUIView (not shown in the code snippet) instance coded in SwiftUI.
A Storyboard Inside a SwiftUI View
Use UIViewControllerRepresentable to embed a storyboard into a SwiftUI view hierarchy. Create a conforming struct and implement the makeUIViewController method. In this method, you load a storyboard and then return a new view controller instance coming from it.
Comparing SwiftUI vs. Storyboard
The following table compares SwiftUI versus storyboard from a software engineering perspective.
SwiftUI is better because it has six points in its favor, versus storyboard having three points.
Next Steps
Use SwiftUI instead of a storyboard for your new UI components. Nevertheless, you aren't compelled to migrate existing storyboards to SwiftUI. Remember that storyboard was introduced over a decade ago, having roots tracing back to NeXT’s Interface Builder in 1992. Then Lindy’s law says it would be around for another decade.
Whether you use SwiftUI, storyboards, or both, your application will benefit from Waldo’s mobile test automation. Learn more about Waldo's SwiftUI support here.
Automated E2E tests for your mobile app
Get true E2E testing in minutes, not months.