简体   繁体   English

如何使用 SwiftUI 观察 TextField 值并结合?

[英]How to observe a TextField value with SwiftUI and Combine?

I'm trying to execute an action every time a textField 's value is changed.每次更改textField的值时,我都会尝试执行一个操作。

@Published var value: String = ""

var body: some View {            
     $value.sink { (val) in
        print(val)
     }
     return TextField($value)       
}

But I get below error.但我得到以下错误。

Cannot convert value of type 'Published' to expected argument type 'Binding'无法将“已发布”类型的值转换为预期的参数类型“绑定”

This should be a non-fragile way of doing it:这应该是一种非脆弱的方式:

class MyData: ObservableObject {
    var value: String = "" {
        willSet(newValue) {
            print(newValue)
        }
    }
}

struct ContentView: View {
    @ObservedObject var data = MyData()
    var body: some View {
        TextField("Input:", text: $data.value)
    }
}

In your code, $value is a publisher, while TextField requires a binding.在您的代码中, $value是一个发布者,而TextField需要一个绑定。 While you can change from @Published to @State or even @Binding , that can't observe the event when the value is changed.虽然您可以从@Published更改为@State甚至@Binding ,但是当值更改时无法观察到事件。

It seems like there is no way to observe a binding.似乎没有办法观察绑定。

An alternative is to use ObservableObject to wrap your value type, then observe the publisher ( $value ).另一种方法是使用ObservableObject来包装您的值类型,然后观察发布者 ( $value )。

class MyValue: ObservableObject {
  @Published var value: String = ""
  init() {
    $value.sink { ... }
  }
}

Then in your view, you have have the binding $viewModel.value .然后在您看来,您拥有绑定$viewModel.value

struct ContentView: View {
    @ObservedObject var viewModel = MyValue()
    var body: some View {
        TextField($viewModel.value)
    }
}

I don't use combine for this.我不为此使用组合。 This it's working for me:这对我有用:

 TextField("write your answer here...",
            text: Binding(
                     get: {
                        return self.query
                       },
                     set: { (newValue) in
                        self.fetch(query: newValue) // any action you need
                                return self.query = newValue
                      }
            )
  )

I have to say it's not my idea, I read it in this blog: SwiftUI binding: A very simple trick我不得不说这不是我的想法,我在这个博客中读到了它: SwiftUI binding:一个非常简单的技巧

如果你想观察value那么它应该是一个State

@State var value: String = ""

You can observe TextField value by using ways,您可以通过使用方法观察TextField值,

import SwiftUI
import Combine

struct ContentView: View {
     
    @State private var Text1 = ""
    @State private var Text2 = ""
    @ObservedObject var viewModel = ObserveTextFieldValue()
    
    var body: some View {
        
            //MARK: TextField with Closures
              TextField("Enter text1", text: $Text1){
                  editing in
                  print(editing)
              }onCommit: {
                  print("Committed")
              }
        
            //MARK: .onChange Modifier
              TextField("Enter text2", text: $Text2).onChange(of: Text2){
                  text in
                     print(text)
              }
    
            //MARK: ViewModel & Publisher(Combine)
              TextField("Enter text3", text: $viewModel.value)
    }
}



class ObserveTextFieldValue: ObservableObject {
  @Published var value: String = ""
  private var cancellables = Set<AnyCancellable>()
  init() {
      $value.sink(receiveValue: {
          val in
          print(val)
      }).store(in: &cancellables)
  }
}

@Published is one of the most useful property wrappers in SwiftUI, allowing us to create observable objects that automatically announce when changes occur that means whenever an object with a property marked @Published is changed, all views using that object will be reloaded to reflect those changes. @Published 是 SwiftUI 中最有用的属性包装器之一,它允许我们创建可观察对象,这些对象会在发生更改时自动通知,这意味着每当带有标记为 @Published 的属性的 object 发生更改时,使用该 ZA8CFDE6331BD59EB2AC96F891 的所有视图都将被重新加载到那些变化。

import SwiftUI

struct ContentView: View {
    @ObservedObject var textfieldData = TextfieldData()
    var body: some View {
        TextField("Input:", text: $textfieldData.data)
    }
}

class TextfieldData: ObservableObject{
   @Published var data: String = ""
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM