Supercharge Your SwiftUI App with Searchable ViewModifier

Saeid Rezaeisadrabadi
4 min readMay 27, 2024

--

In this post, I want to talk about how to use searchable view modifier in SwiftUI.
List views can hold from one to an uncountable number of items. As the number of items in a list increases, it is usually helpful to provide users with the ability to search through the list for a specific item without having to scroll through the whole list.
SwiftUI’s searchable view modifier is a powerful tool for adding a search bar to your app, letting users filter and find information efficiently.

Getting Started

Add a new Swift file to the project called Food, which will contain the data used for the project. We use a struct to model different types of food. The struct has two properties, a string with the name of the food, and a category, which is an enum representing the type of food:

struct Food: Hashable {

enum Category: String {
case fruit
case meat
case vegetable
}
var name: String
var category: Category
}

Let’s add some sample data to illustrate how to search a list. Add a type extension after the struct declaration. Here, we choose to extend an array of Food so our code will look concise thanks to Swift’s powerful type inference:

extension Food {
static let sampleFood: [Food] = [
Food(name: "Apple", category: .fruit),
Food(name: "Pear", category: .fruit),
Food(name: "Orange", category: .fruit),
Food(name: "Lemon", category: .fruit),
Food(name: "Strawberry", category: .fruit),
Food(name: "Plum", category: .fruit),
Food(name: "Banana", category: .fruit),
Food(name: "Melon", category: .fruit),
Food(name: "Watermelon", category: .fruit),
Food(name: "Peach", category: .fruit),
Food(name: "Pork", category: .meat),
Food(name: "Beef", category: .meat),
Food(name: "Lamb", category: .meat),
Food(name: "Goat", category: .meat),
Food(name: "Chicken", category: .meat),
Food(name: "Turkey", category: .meat),
Food(name: "Fish", category: .meat),
Food(name: "Crab", category: .meat),
Food(name: "Lobster", category: .meat),
Food(name: "Shrimp", category: .meat),
Food(name: "Carrot", category: .vegetable),
Food(name: "Lettuce", category: .vegetable),
Food(name: "Tomato", category: .vegetable),
Food(name: "Onion", category: .vegetable),
Food(name: "Broccoli", category: .vegetable),
Food(name: "Cauliflower", category: .vegetable),
Food(name: "Eggplant", category: .vegetable),
Food(name: "Swiss Chard", category: .vegetable),
Food(name: "Spinach", category: .vegetable),
Food(name: "Zucchini", category: .vegetable),
]
}

In the ContentView file. Before the ContentView struct’s body, add a State variable to hold the search text and add another variable to hold the sample data, in our case an array of Food instances, which we populate with the sample data defined in the previous step:

@State private var searchText = ""
let food = Food.sampleFood

Replace the ContentView struct’s body with a NavigationStack, containing a List, and to display the search results, a navigationTitle modifier, and a .searchable modifier:

NavigationStack {
List {
ForEach(searchResults, id: \.self) { item in
LabeledContent(item.name) { Text("\(item.category.rawValue)") }

}
}
.searchable(text: $searchText)
}

Let’s add the searchResults computed property, below the body variable, which returns an array of elements representing the result of the search:

var searchResults: [Food] {
if searchText.isEmpty {
return food
} else {
return food.filter { $0.name.lowercased().contains(searchText.lowercased()) }
}
}

The resulting live preview should look as follows:

In this example, we have a list of foods and a searchText state variable. The searchable modifier is applied to the list, binding the search text to searchText. The value of searchResults is used by the List view in the ForEach struct to display a filtered list of items based on the searched text.
For each item in the list, we use the LabeledContent container view to display the name and the category of the food.

Placement and Customization

By default, SwiftUI automatically positions the search bar within your navigation view. You can customize this placement using the placement parameter of the searchable modifier. Here are the available options:

  • .automatic: Let SwiftUI decide the best placement (default).
  • .navigationBarDrawer: Place the search bar in the navigation bar.
  • .sidebar: Place the search field in the sidebar of a navigation view.
  • .toolbar: Place the search field in the toolbar.
  • .navigationBarDrawer : Place the search field in the navigation bar using the specified display mode.

Additionally, you can provide a custom prompt string using the prompt parameter. This text appears as a placeholder within the search bar.

Conclusion

The searchable modifier empowers you to create user-friendly search functionalities in your SwiftUI apps. By following these steps and exploring its advanced features, you can streamline user interaction and make your app's information more discoverable.

To access the code discussed in this post, visit here.

--

--

Saeid Rezaeisadrabadi
Saeid Rezaeisadrabadi

Written by Saeid Rezaeisadrabadi

Over 8 years of experience in iOS software development

No responses yet