Supercharge Your SwiftUI App with Searchable ViewModifier
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.