SwiftUI - 如何在另一个视图中响应 TextField onCommit?

Posted

技术标签:

【中文标题】SwiftUI - 如何在另一个视图中响应 TextField onCommit?【英文标题】:SwiftUI - how to respond to TextField onCommit in an other View? 【发布时间】: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 并启动数据库搜索 - 我该怎么做?

【问题讨论】:

【参考方案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 调用:参数应以括号结尾,以防止出现“表达式解析为未使用的函数”错误

以上是关于SwiftUI - 如何在另一个视图中响应 TextField onCommit?的主要内容,如果未能解决你的问题,请参考以下文章

如何响应 SwiftUI 中的视图生命周期事件?

如何告诉 SwiftUI 视图绑定到多个嵌套的 ObservableObject

我们如何在 SwiftUi 的另一个视图中传递布尔状态

如何在 SwiftUI 中关闭工作表时刷新视图

如何通过拖动在SwiftUI ZStack中重新排列视图

SwiftUI 从另一个视图中捕获 Picker 值