Creating a Searchable List in SwiftUI

Starting SwiftUI 3.0 and iOS 15, Apple made searching through a list a lot easier. With a simple modifier, SwiftUI will automatically add a search field in the best possible place it can find.

Effortlessly search through a list.

Only on iOS 15 and higher

The searchable(text:placement) modifier discussed in this tutorial is only supported in applications running on iOS 15.0 and higher. You'll need Xcode 13 and need to set your Xcode project's iOS target version to iOS 15.0 or higher, or wrap the code presented in this section in an if #available(iOS 15.0, *).

Create a list

First, we'll create an Author model. Each author will have an id and a name. Below it, let's create an array of authors. We'll only need to provide the name, as the id is already set inside of the struct.

struct Author: Identifiable {
    var id = UUID()
    var name: String
}

var authors = [Author(name: "Meng To"), Author(name: "Stephanie Diep"), Author(name: "Willie Yam"), Author(name: "Sai Kambampati")]

..

We'll take that authors array and display it in a List. For each item, we'll display the name of the author.

List(authors) {
		Text($0.name)
}

..

Wrap in NavigationView

In order to make the searchable modifier work properly, we'll need to wrap the List in a NavigationView.

NavigationView {
	List(authors) {
		Text($0.name)
	}
}

..

Create text state

The searchable modifier requires a binding text, so let's create a private state at the top.

@State private var text = ""

..

And pass the text state as a binding variable to the searchable(text:placement:) modifier. Remember to add the searchable modifier on the NavigationView, as it won't work otherwise.

.searchable(text: $text)

Add updatedAuthors array

Let's add another state at the top, called updatedAuthors. We'll initialize it as an empty array to start with, and update it when the user searches for an author.

@State private var updatedAuthors: [Author] = []

onChange event

On change of the text, we'll update the updatedAuthors array, by filtering the authors array and returning any author where the name contains the letters of the search value.

.onChange(of: text) { searchValue in
		updatedAuthors = authors.filter { $0.name.contains(searchValue)}
}

..

Update the list

We'll update the List and the array we'll display whenever the text isn't an empty string.

List(text == "" ? authors : updatedAuthors) {
		Text($0.name)
}

Find below the final result.

..

Comments