Blog post
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 a settings screen in our application. SwiftUI is a great choice for this kind of task since it contains components like Form. If we want to present or push a 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.
Check Code Snippet here.
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 a 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.
Check Code Snippet here
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 a SwiftUI 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 standard UIKit routine for adding the child controllers.
Check Code Snippet here.
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 the UIKit components and use them in our SwiftUI views.
We can do this by following these steps:
- First, we need to create a SearchBar struct and conform it to UIViewRepresentable. When we conform to this protocol we will need to implement makeUIView and updateUIView methods. In makeUIView we create and set up our view. The system calls this method only once. To track state changes we use the updateUIView method and SwiftUI calls this method for any changes affecting the corresponding UIKit view;
- Create a @Binding variable for text;
- Create a Coordinator class inside our struct. It needs to be a class because it must inherit from NSObject. We will also conform it to UISearchBarDelegate. Here we will also create a @Binding variable for text and implement the UISearchBarDelegate methods we need;
- The last thing to do is implement the makeCoordinator method so we can create an instance of our Coordinator class.
Check Code Snippet here.
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. Furthermore, 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.