nickreps
nickreps

Reputation: 1080

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.

Below is an image of the cancel button I am referring to:enter image description here

Upvotes: 9

Views: 6526

Answers (3)

jian gao
jian gao

Reputation: 63

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)
    }
}

Upvotes: 2

CSolanaM
CSolanaM

Reputation: 3368

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")
        }
    }
}

Upvotes: 4

jnpdx
jnpdx

Reputation: 52565

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

Upvotes: 18

Related Questions