我有一个用于搜索数组中的项目的文本字段,并且我正在使用一个模型,该模型具有已发布的文本属性,绑定到该字段以在每次文本更改时调用搜索函数。
我当前的问题是,每当文本字段发生任何事情时,它都会发送一个已更改的通知,因此第一次出现时它会发送一个通知,每次它聚焦、散焦或键入一个字母时它会发送两个通知.
这是代码的简化示例:
struct ContentView: View {
@ObservedObject var model = Model()
@FocusState var focused: Bool
var body: some View {
VStack {
TextField("Field", text: $model.text)
.submitLabel(.search)
.focused($focused)
Text("Field has sent changes \(model.textChanged) times")
Button(action: { focused = false }) {
Text("Defocus")
}
}
.padding()
}
}
class Model: ObservableObject {
@Published var text: String = ""
@Published var textChanged: Int = 0
private var cancellables = Set<AnyCancellable>()
init() {
$text
.sink { text in
self.textChanged += 1 // This is where i am doing my search call in the actual code
}
.store(in: &cancellables)
}
}
我尝试在 TextField 上使用 .onReceive ,在视图上使用 .onChange($text) 而不是 .sink ,但这并没有改变任何东西。我知道这是 TextField 的默认行为,但我只想在文本更改时执行搜索,而不是每次字段发生问题时执行搜索。将搜索调用放入文本属性的 didSet 中也不是一个选项。
您可以将
.onChange
附加到 TextField
(或者实际上您可以将其附加到 body
的任何部分):
@State private var counter = 0
var body: some View {
VStack {
TextField("Field", text: $model.text)
.submitLabel(.search)
.focused($focused)
.onChange(of: model.text) {
counter += 1
}
Text("Field has sent changes \(model.textChanged) times, counter=\(counter)")
Button(action: { focused = false }) {
Text("Defocus")
}
}
.padding()
}