SwiftUI 2.0 & UIKit & Storyboard (Part 3)


Part 3: Storyboard & SwiftUI 2.0

The article is broken in three different parts:

The third part is about using SwiftUI 2.0 elements in a Storyboard application.

Use SwiftUI views from UIKit views and the Storyboard

This is the opposite of the 2 previous section, and is useful to add new views to a legacy application or refactor parts of a legacy application using SwiftUI.

The XCode Project

Create a new SwiftUI App project

Name the project

Create a new SwiftUI View

Name it

Then populate it with UI elements and make it the initial view controller

Now we have a Storyboard project containing a storyboard with a UIViewController that contains a label and a button ...

The Storyboard UIViewController

The UIViewController in the storyboard has its own subclass ViewController.

Rename the subclass to UIKitViewController and add an IBAction linked to the button TouchUpInside event:

UIKitViewController.swift
import UIKit
import SwiftUI

class UIKitViewController: UIViewController {
    @IBAction func toSwiftUI(_ sender: Any) {
    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

To display the SwiftUI view, use a UIHostingController:

Swift
UIHostingController(rootView: _)

In the IBAction of the UIKitViewController, init a UIHostingController with SwiftUIView, then use it just like a normal UIViewController to present the SwiftUI view:

UIKitViewController.swift
import UIKit
import SwiftUI

class UIKitViewController: UIViewController {
    @IBAction func toSwiftUI(_ sender: Any) {
        let view = UIHostingController(rootView: SwiftUIView())
        self.present(view, animated: true, completion: nil)
    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

Now let's write the SwiftUI view.

The SwiftUI View

The SwiftUI View is composed of 4 elements:
- A Text element displaying the text "SwiftUI"
- A Text element displaying the content of the labelText variable
- A TextField element binded to the inputText variable
- A button to change the content of labelText to the content of inputText

SwiftUIView.swift
import SwiftUI

struct SwiftUIView: View {
    @State var labelText = "Initial Text"
    @State var inputText = ""

    var body: some View {
        VStack {
            Text("SwiftUI")
            Spacer()
            Text(labelText)
            Spacer()
            TextField("Input", text: $inputText)
            Spacer()
            Button {
                labelText = inputText
                inputText = ""
            } label: {
                Text("Change Text")
            }
        }
    }
}

Now let's test the IBAction!

The App

Launch the App, and in the Storyboard view, click on the To SwiftUI! button to present the SwiftUI view:

In the SwiftUI view input some new text in the textfield:

Then, click on the Change Text button, and the "Initial Text" in the second Text element gets replaced with the new text:

It works!