【问题标题】:SwiftUI - how to respond to TextField onCommit in an other View?SwiftUI - 如何在另一个视图中响应 TextField onCommit?
【发布时间】:2020-08-10 12:00:11
【问题描述】:

我制作了一个SearchBarView 视图以在各种其他视图中使用(为了清楚起见,我删除了所有布局修饰符,例如颜色和填充):

struct SearchBarView: View {
    @Binding var text: String
    @State private var isEditing = false
    
    var body: some View {
        HStack {
            TextField("Search…", text: $text, onCommit: didPressReturn)
                 .overlay(
                    HStack {
                        Image(systemName: "magnifyingglass")
                            .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
                        
                        if isEditing {
                            Button(action: {
                                self.text = ""
                            }) {
                                Image(systemName: "multiply.circle.fill")
                            }
                        }
                    }
                )
    }
    
    func didPressReturn() {
        print("did press return")
    }
}

List 中过滤数据看起来很棒。

但现在我想使用SearchBarView 来搜索外部数据库。

struct SearchDatabaseView: View {
    @Binding var isPresented: Bool
    @State var searchText: String = ""

    var body: some View {
        NavigationView {
            VStack {
                SearchBarView(text: $searchText)
                // need something here to respond to onCommit and initiate a network call.

            }
            .navigationBarTitle("Search...")
            .navigationBarItems(trailing:
                Button(action: { self.isPresented = false })  {
                    Text("Done")
            })
        }
    }
}

为此,我只想在用户点击返回时开始网络访问。所以我在SearchBarView中添加了onCommit部分,而didPressReturn()函数确实只有在点击return时才会调用。到目前为止,一切顺利。

我不明白的是,包含 SearchBarViewSearchDatabaseView 如何响应 onCommit 并启动数据库搜索 - 我该怎么做?

【问题讨论】:

    标签: swiftui textfield


    【解决方案1】:

    这是可能的方法

    struct SearchBarView: View {
        @Binding var text: String
        var onCommit: () -> () = {}   // inject callback
    
        @State private var isEditing = false
        
        var body: some View {
            HStack {
                TextField("Search…", text: $text, onCommit: didPressReturn)
                     .overlay(
                        HStack {
                            Image(systemName: "magnifyingglass")
                                .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
                            
                            if isEditing {
                                Button(action: {
                                    self.text = ""
                                }) {
                                    Image(systemName: "multiply.circle.fill")
                                }
                            }
                        }
                    )
        }
        
        func didPressReturn() {
            print("did press return")
           // do internal things...
    
           self.onCommit()      // << external callback
        }
    }
    

    所以现在在SearchDatabaseView 你可以

    VStack {
        SearchBarView(text: $searchText) {
          // do needed things here ...
        }
    }
    

    【讨论】:

    • 这是否会影响其他使用SearchBarView 但不需要onCommit 要求的视图,例如List 过滤? (我的 Mac 不在身边,直到今天晚些时候才能自己测试)。
    • 不,正如所见 - let onCommit: () -&gt; () = {} - 有默认的空闭包
    • 我在你写// do needed things here ...的地方放了什么?当我在SearchBarView(text: $searchText) 之后添加大括号时出现Extra trailing closure passed in call 错误。
    • 那必须是变量var onCommit: () -&gt; () = {}。已更新修复。
    • 太棒了!请注意 onCommit 中的 didPressReturn 调用:参数应以括号结尾,以防止出现“表达式解析为未使用的函数”错误
    猜你喜欢
    • 2022-11-01
    • 2020-06-21
    • 2019-10-23
    • 1970-01-01
    • 2023-01-25
    • 2021-10-15
    • 1970-01-01
    • 2022-08-23
    • 2019-10-23
    相关资源
    最近更新 更多