Implement native Search Bar in SwiftUI
Get automatic hide/show on scroll, clear and cancel button, and search key in the keyboard.
In this article, I share how to properly implement a search bar in a SwiftUI app by wrapping the UINavigationController.
This approach gives us the advantage of achieving all the expected behaviours including automatic hide/show on scroll, clear and cancel button, and search key in the keyboard among others.
Time for code!
Wrap UINavigationController with Search Bar
To properly implement a native search bar in SwiftUI, we wrap the UINavigationController using the UIViewControllerRepresentable protocol.
The reason why we don’t wrap the UISearchBar or the UISearchController is because then we’re not able to get all the desired behaviours. Most notable of them would be the automatic hide/show of search bar on scrolling, and the search bar replacing the navigation bar while searching.
The search bar is originally a navigation item and hence it is essential to wrap the UINavigationController to get the optimal user experience.
The above code for the wrapped SwiftUI view of the UINavigationController can be used as-is, and of-course, modifications are always possible to suit your app requirements.
In our project, apart from getting all the desired search behaviours and animations, we wanted two specific things —
- Call the search function and filter the list when the search key is tapped.
- Show the full data (without filter) when cancel button is pressed.
To achieve these two things, and automatic view updates when SwiftUI state changes, we implemented the coordinator class which initializes the view controller, updates it, and has delegate methods for the search controller.
Our SearchNavigation wrapper takes the search string, search action, cancel action, and enclosed SwiftUI view as parameters. The enclosed SwiftUI view becomes a trailing closure and hence behaves exactly like the SwiftUI NavigationView, except it has the powerful search bar now!
Our SearchNavigation view is ready and can be used in place of the NavigationView like this —
As is evident, our SearchNavigation view is totally reusable and can be configured with different logic for ‘search’ and ‘cancel’ in each view as per the requirements.
It is also amazing how we’re able to update the navigation title by using the SwiftUI navigationBarTitle modifier.
That’s it! We’re done!