Integrating UIKit into SwiftUI: the best of both worlds
SwiftUI was announced at WWDC 2019 and is only available on devices running iOS 13 and above. Many improvements and new APIs have been added to SwiftUI since its introduction, to the point that, at the time of this writing, we can create an app in SwiftUI without using any UIKit components.
However, if you’re dealing with legacy code written in UIKit, and have the need to integrate the code in your SwiftUI app, Apple provides a way to do this. UIViews and UIViewControllers can be seamlessly placed inside SwiftUI views and vice versa.
In this recipe, we’ll look at how to integrate UIKit APIs in SwiftUI. We will create a project that wraps instances of UIActivityIndicatorView
to display an indicator in SwiftUI.
Getting ready
Open Xcode and create a SwiftUI project named UIKitToSwiftUI.
How to do it…
We can display UIKit views in SwiftUI by using the UIViewRepresentable
protocol. Follow these steps to implement the UIActivityIndicatorView
in SwiftUI:
- Within the Xcode menu, click File | New | File and select Swift File. Name the view
ActivityIndicator
. - Replace the
import Foundation
statement withimport SwiftUI
:import SwiftUI
- Modify the code in
ActivityIndicator
to use theUIViewRepresentable
protocol:struct ActivityIndicator: UIViewRepresentable { var animating: Bool func makeUIView(context: Context) -> UIActivityIndicatorView { return UIActivityIndicatorView() } func updateUIView(_ activityIndicator: UIActivityIndicatorView, context: Context) { if animating { activityIndicator.startAnimating() } else { activityIndicator.stopAnimating() } } }
- Let’s open the
ContentView.swift
file and replace the struct with the following code to make use of theActivityIndicator
instance that we just created. Let’s also add aToggle
control to turn the indicator on or off:struct ContentView: View { @State private var animate = true var body: some View { VStack{ ActivityIndicator(animating: animate) HStack{ Toggle(isOn: $animate){ Text("Toggle Activity") } }.padding() } } }
- The resulting
ContentView
preview should look like this:
Figure 1.18: UIKit UIActivityIndicatorView inside our SwiftUI view
How it works…
UIKit views can be implemented in SwiftUI by using the UIViewRepresentable
protocol to wrap the UIKit views. In this recipe, we make use of a UIActivityIndicatorView
by first wrapping it with a UIViewRepresentable
.
In our ActivityIndicator.swift
file, we implement a struct that conforms to the UIViewRepresentable
protocol. This requires us to implement both the makeUIView
and updateUIView
functions. The makeUIView
function creates and prepares the view, while the updateUIView
function updates the UIView
when the animation changes.
Important Note
You can implement the preceding features in iOS 14+ apps by using SwiftUI’s ProgressView
. The purpose of the recipe was to show how to integrate a UIKit view with SwiftUI.
See also
Check out the Exploring more views and controls recipe at the end of this chapter for more information on ProgressView
.
Apple’s tutorial on how to integrate UIKit and SwiftUI:
https://developer.apple.com/tutorials/swiftui/interfacing-with-uikit