SwiftUI · · 4 min read

How to Implement Search for SwiftUI List Using Searchable

How to Implement Search for SwiftUI List Using Searchable

Prior to iOS 15, SwiftUI didn’t come with a built-in modifier for handling search in List views. Developers have to create your own solution. We have written a tutorial showing you how to implement a search bar in SwiftUI using TextField and display the search result. With the release of iOS 15, the SwiftUI framework brings a new modifier named searchable to List views.

In this tutorial, we will look into this modifier and see easily it is to implement search for a list.

Basic Usage of Searchable

Search-bar-ios15-demo

Let’s suppose you have created a list view to display a set of article and want to provide a search bar for filtering the articles. To add a search bar to the list view, all you need to do is declare a state variable to hold the search text and attach a searchable modifier to the NavigationView like this:

struct SearchListView: View {

    @State var articles = sampleArticles
    @State private var searchText = ""

    var body: some View {
        NavigationView {
            .
            .
            .
        }
        .searchable(text: $searchText)
    }
}

SwiftUI automatically renders the search bar for you and put it under the navigation bar title.

swiftui-searchable-search-bar

By default, it displays the word Search as a placeholder. In case if you want to change it, you can write the .searchable modifier like this and use your own placeholder value:

.searchable("Search articles...", text: $searchText)

Search Bar Placement

The .searchable modifier has a placement parameter for you to specify where to place the search bar. By default, it’s set to .automatic. On iPhone, the search bar is placed under the navigation bar title. When you scroll up the list view, the search bar will be hidden.

searchable-permanent-search-bar-placement

If you want to permanently display the search field like the one shown above, you can change the .searchable modifier and specify the placement parameter like this:

.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))

So far, we attach the .searchable modifier to the navigation view. You can actually attach it to the List view and achieve the same result on iPhone.

That said, the placement of the .searchable modifier affects the position of the search field when using Splitview on iPad OS. Take a look at the following sample code:

NavigationView {
    List {
        ForEach(articles) { article in
            ArticleRow(article: article)
        }

        .listRowSeparator(.hidden)

    }
    .listStyle(.plain)

    Text("Article Content")


    .navigationTitle("AppCoda")

}
.searchable(text: $searchText)

As usual, we attach the .searchable modifier to the navigation view. In this case, the search bar is displayed on the sidebar of the split view.

searchable-on-ipados

What if you want to place the search field in the detail view? You can just attach the .searchable modifier to the Text view of the sample code.

Text("Article Content")
    .searchable(text: $searchText)

iPadOS will then render the search bar at the top right corner of the detail view.

searchable-ipados-search-bar

Again, you can further change the placement of the search bar by adjusting the value of the placement parameter. Here is an example:

.searchable(text: $searchText, placement: .navigationBarDrawer)

By setting the placement parameter to .navigationBarDrawer, iPadOS places the search field beneath the navigation bar title.

searchable-ipados-navigationbardrawer

Performing Search and Displaying Search Results

searchable-perform-search

There are different ways to filter the list of data. You may create a computed property that performs the data filtering in real-time. Alternatively, you can attach the .onChange modifier to keep track of the change of the search field. Whenever the user types in the search field, you perform the search in real-time. Here is a sample code snippet:

NavigationView {
    List {
        ForEach(articles) { article in
            ArticleRow(article: article)
        }

        .listRowSeparator(.hidden)

    }
    .listStyle(.plain)

    .navigationTitle("AppCoda")
}
.searchable(text: $searchText)
.onChange(of: searchText) { searchText in

    if !searchText.isEmpty {
        articles = sampleArticles.filter { $0.title.contains(searchText) }
    } else {
        articles = sampleArticles
    }
}

Adding Search Suggestions

The .searchable modifier lets you add a list of search suggestions for displaying some commonly used search terms or search history. For example, you can create tappable search suggestion like this:

.searchable(text: $searchText) {
    Text("SwiftUI").searchCompletion("SwiftUI")
    Text("iOS 15").searchCompletion("iOS 15")
}

This displays a search suggestion with two tappable search terms. Users can either type the search keyword or tap the search suggestion to perform the search.

searchable-swiftui-perform-search

Summary

iOS 15 brings another welcome feature for the SwiftUI framework. The .searchable modifier simplifies the implementation of search bar and save us time from creating our own solution. The downside is that this feature is only available on iOS 15 (or later). If you are building an app that needs to support the older versions of iOS, you will still need to build your own search bar.

Read next