'SwiftUI - Perform action when cancel is clicked - .searchable function
When using the .searchable(text: $text) function, a cancel button appears in the search bar when searching.
Is there any way to perform an action when the cancel button is clicked? I would like to call a function when cancel is clicked, but cannot figure out how to perform an action when cancel is tapped.
The Apple Documentation does not mention anything about this. Back in UIKit there was the func searchBarCancelButtonClicked(searchBar: UISearchBar) { to do this.
Solution 1:[1]
You can use the isSearching environment value (https://developer.apple.com/documentation/swiftui/environmentvalues/issearching?changes=_6) to see if a search is being performed. To do an action upon cancelation, you could watch for a change from true to false using onChange:
struct ContentView: View {
@State private var searchText = ""
@Environment(\.dismissSearch) var dismissSearch
var body: some View {
NavigationView {
VStack {
ChildView()
Text("Searching for \(searchText)")
}
.searchable(text: $searchText)
.navigationTitle("Searchable Example")
}
}
}
struct ChildView : View {
@Environment(\.isSearching) var isSearching
var body: some View {
Text("Child")
.onChange(of: isSearching) { newValue in
if !newValue {
print("Searching cancelled")
}
}
}
}
Probably important to note that it seems like isSearching has to be inside a child view of the searchable modifier in order for it to work properly
Solution 2:[2]
Based on @jnpdx 's answer, something equivalent, but more generic is:
struct SearchView<Content: View>: View {
@Environment(\.isSearching) var isSearching
let content: (Bool) -> Content
var body: some View {
content(isSearching)
}
init(@ViewBuilder content: @escaping (Bool) -> Content) {
self.content = content
}
}
And then, use it like:
struct ContentView: View {
@State private var searchText = ""
@Environment(\.dismissSearch) var dismissSearch
var body: some View {
NavigationView {
VStack {
SearchView { isSearching in
Text("Child")
.onChange(of: isSearching) { newValue in
if !newValue {
print("Searching cancelled")
}
}
}
Text("Searching for \(searchText)")
}
.searchable(text: $searchText)
.navigationTitle("Searchable Example")
}
}
}
Solution 3:[3]
use isEmpty and onAppear.
struct SearchView: View {
@State var text: String = ""
var body: some View {
NavigationView {
VStack {
if text.isEmpty {
main.onAppear {
print("empty")
// code here
}
} else {
main
}
}.searchable(text: $text)
.onSubmit(of: .search) {
print("submit")
}
}
}
var main: some View {
Text("search").searchable(text: $text)
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | jnpdx |
| Solution 2 | CSolanaM |
| Solution 3 | jian gao |

