When using a table, you typically manage a lot of data, so some basic operations include searching and selecting. In this post, you’ll learn how to search for data in a table and how to select a row.
Search
Before we start, consider that our starting point is the code from Episode I, which you can obtain here .
The first step is to add the search functionality. To do this, we need to incorporate a NavigationStack into our code:
NavigationStack {
Table(foundBeers, sortOrder: $sortOrder) {
// the same code
}.onAppear {
Task {
await getBeers()
}
}.onChange(of: sortOrder) {
beers.sort(using: sortOrder)
}.searchable(text: $searchText, prompt: Text("Search by name"))
}
Therefore, we added the searchable modifier (similar to how it’s done for a list). The searchText will contain the text entered by the user, and foundBeers will hold the results of the search.
var foundBeers: [Beer] {
if searchText.count == 0 {
return self.beers
} else {
return self.beers.filter({(beer: Beer) -> Bool in
return beer.name.lowercased().contains(searchText.lowercased())
})
}
}
If the search field is empty, this variable contains all the beers. Otherwise, it filters by name. The filter function retrieves all the beers that match the condition where the name contains the searchText – all in lowercase to avoid case sensitivity.
Combining the pieces:
struct ContentView: View {
@State var beers: [Beer] = []
@State var page = 0
@State private var sortOrder = [KeyPathComparator(\Beer.name, order: .reverse)]
@State private var searchText = ""
var body: some View {
NavigationStack {
Table(foundBeers, sortOrder: $sortOrder) {
TableColumn("Name", value: \.name)
TableColumn("First Brew", value: \.first_brewed)
TableColumn("ABV") { beer in
Text("\(beer.abv)")
}
TableColumn("Image") { beer in
AsyncImage(url: URL(string: beer.image_url)) { image in
image.resizable().scaledToFit()
} placeholder: {
ProgressView()
}
.frame(width: 100, height: 100)
}
}.onAppear {
Task {
await getBeers()
}
}.onChange(of: sortOrder) {
beers.sort(using: sortOrder)
}.searchable(text: $searchText, prompt: Text("Search by name"))
}
}
var foundBeers: [Beer] {
if searchText.count == 0 {
return self.beers
} else {
return self.beers.filter({(beer: Beer) -> Bool in
return beer.name.lowercased().contains(searchText.lowercased())
})
}
}
func getBeers() async {
// get from previous
}
}

Select
To select and highlight an item, we need to make some minor changes:
- Add a variable that will contain the selected item or items.
- Use a different initialization function for the table.
For the first point:
@State private var beerSelected: Beer.ID?
Considering that there might be a selection or not, the beerSelected variable is optional (based on the identifiable property). If you want to enable multiple selections, replace Beer.ID? with an empty Set<Beer.ID>.
@State private var beerSelected: Set<Beer.ID> = Set<Beer.ID>()
For the second point on the list:
Table(beersSearched, selection: $beerSelected, sortOrder: $sortOrder) {

Please select the right beer!
Note: English is not my native language, so I apologize for any errors. I use AI solely to generate the banner of the post; the content is human-generated.