Reputation: 4300
I'm trying to understand how to know when a user has tapped into the search field in an iOS app that is using the .searchable modifier. The Apple docs say one can get the Environment value to find out when the user interacts with a search field that’s produced by one of the searchable modifiers, like searchable(text:placement:prompt:)
However this first code does not work. The Text always says Not Searching. I must be missing something fundamental:
struct ContentView: View {
@Environment(\.isSearching) var isSearching
@State private var searchText: String = ""
var items = ["One", "Two", "Three", "Four", "Five"]
var body: some View {
NavigationStack {
VStack {
Text(isSearching ? "Searching" : "Not Searching")
List {
ForEach(searchResults, id: \.self) { item in
Text(item)
}
}
.listStyle(PlainListStyle())
.searchable(text: $searchText)
}//v
.padding()
}//nav
}//body
private var searchResults: [String] {
if searchText.isEmpty {
return items
} else {
return items.filter({ item in
item.contains(searchText)
})
}
}//var search results
}//struct
But, if I extract the bulk of the code to another view, this does work:
struct ContentView2: View {
@State private var searchText: String = ""
var body: some View {
NavigationStack {
SearchedView2 (searchText: $searchText)
.searchable(text: $searchText)
}//nav
}//body
}//struct
struct SearchedView2: View {
@Environment(\.isSearching) var isSearching
@Binding var searchText: String
var items = ["One", "Two", "Three", "Four", "Five"]
var body: some View {
VStack {
Text(isSearching ? "Searching" : "Not Searching")
List {
ForEach(searchResults, id: \.self) { item in
Text(item)
}
}
.listStyle(PlainListStyle())
}//v
.padding()
}//body
private var searchResults: [String] {
if searchText.isEmpty {
return items
} else {
return items.filter({ item in
item.contains(searchText)
})
}
}//var search results
}//struct
I'm confused. Why doesn't the first code work? Any guidance would be appreciated. Xcode 14.0.1 iOS 16.0
Upvotes: 2
Views: 1786
Reputation: 498
Let's give a look at the documentation. The @Environment()
wrapper is initialized with a given environment value \.isSearching
, which represents the context within which it was called - SearchingExampl()
, then it tries to find the search field created by the .searchable()
modifier and provide all its functionality, including the isSearching
observer.
struct SearchingExample: View {
@State private var text = ""
var body: some View {
NavigationView {
SearchedView()
.searchable(text: $text)
}
}
}
struct SearchedView: View {
@Environment(\.isSearching) private var isSearching
var body: some View {
Text(isSearching ? "Searching!" : "Not searching.")
}
}
Theory:
https://developer.apple.com/documentation/swiftui/environment?language=swift
https://developer.apple.com/documentation/swiftui/environmentvalues
https://developer.apple.com/documentation/swiftui/environmentvalues/issearching
Practice:
https://developer.apple.com/documentation/swiftui/adding-search-to-your-app
Upvotes: 3