Mixing UIKit and SwiftUI
Soon it will be two years since Apple announced SwiftUI
during WWDC
’19. As this framework slowly matures and we increment our application’s deployment target we can start adopting it in our codebase. If your application deployment target is ≥ 13 you should definitely try SwiftUI
. The great thing is we don’t need to go all in on SwiftUI
or UIKit
but we can easily combine them. In this blog post we are going to go through several examples how we can mix them and make the most out of it.
Creating view controller with SwiftUI root view
Let’s say we decided to implement settings screen in our application. SwiftUI
is great choice for this kind of task since it contains components like Form
. If we want to present or push UIViewController
with SwiftUI
view all we need to do is create UIHostingController
, add our root view and then present it or push it depending on our needs.
What if we wanted to do the same but add some more customisation, such as embed our UIViewController
into UITabBarViewController
and set our UITabBarItem
with title, image and selected image?
To do so, let’s go ahead and create SettingsViewController
and make it subclass of UIHostingController
. Here we will need to specify which view we are going to create. In our case it will be SettingsView
. The only thing left to do here is set the properties for our UITabBarItem
.
It is also worth mentioning that the same technique works for both macOS and watchOS development. Instead of using UIHostingController
like in our example we can use NSHostingController
and WKHostingController
.
Adding SwiftUI view as a child
Adding aSwiftUI
view as a child to the existing view controller is also very straightforward. We initialise the settingsView, add it to UIHostingController
and then follow the standardUIKit
routine for adding the child controllers.
Using UIKit components in SwiftUI
While SwiftUI
is full of great components and we are getting more and more each year, sometimes we need to go back to UIKit
. The first component that comes to my mind is UISearchBar
. There is no out of the box SwiftUI
solution that can replace UISearchBar
. But that shouldn’t be a big problem since we can easily adapt theUIKit
components and use them in our SwiftUI
views.
We can do this by following these steps:
- First, we need to create
SearchBar
struct and conform it toUIViewRepresentable
. When we conform to this protocol we will need to implementmakeUIView
andupdateUIView
methods. InmakeUIView
we create and setup our view. The system calls this method only once. To track state changes we use theupdateUIView
method andSwiftUI
calls this method for any changes affecting the correspondingUIKit
view; - Create a
@Binding
variable for text; - Create a Coordinator class inside our struct. It needs to be class because it must inherit from
NSObject
. We will also conform it toUISearchBarDelegate
. Here we will also create@Binding
variable for text and implement theUISearchBarDelegate
methods we need; - The last thing to do is implement
makeCoordinator
method so we can create an instance of ourCoordinator
class.
Final thoughts
In this article we showed several different examples of how we can combine UIKit and SwiftUI. If you have a chance to adopt SwiftUI in your application you can follow this approach and start by adding small views. This way you will learn the basics of using a new framework and once you start to work on an app from scratch you’ll notice how much you already know and it’s easy to build on that. However, continuing to write the apps with UIKit is also perfectly fine. Not only does UIKit power a lot of SwiftUI, we are also getting new UIKit API’s every WWDC (such asCellRegistration
, DiffableDataSources
, CompositionalLayout
).
Finally, if you are looking for some resources to learn more about SwiftUI
I highly recommend reading the book Thinking in SwiftUI.
Thank you for reading and a big thank you to Jelena Matejić for the design!
Would you like to join Undabot? Check out the open positions on our Careers page.
Stay up to date with Undabot news by subscribing to our monthly newsletter.