SwiftUI - 单击取消时执行操作 - .searchable 函数

SwiftUI - Perform action when cancel is clicked - .searchable function

使用.searchable(text: $text)功能时,搜索时搜索栏会出现取消按钮。

有什么方法可以在单击取消按钮时执行操作吗?我想在点击取消时调用一个函数,但无法弄清楚点击取消时如何执行操作。

Apple Documentation 对此没有提及任何内容。回到 UIKit 中,func searchBarCancelButtonClicked(searchBar: UISearchBar) { 可以做到这一点。

下面是我指的取消按钮的图片:

您可以使用 isSearching 环境值 (https://developer.apple.com/documentation/swiftui/environmentvalues/issearching?changes=_6) 查看是否正在执行搜索。要在取消时执行操作,您可以使用 onChange:

观察从 truefalse 的变化

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

可能需要注意的是,似乎 isSearching 必须位于 searchable 修饰符的子视图中才能正常工作

根据@jnpdx 的回答,等效但更通用的是:

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

然后,像这样使用它:

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

使用 isEmptyonAppear

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