我目前正在构建一个搜索字段,当其值发生变化时应该执行一些操作。这是我的观点:
struct SearchView: View {
@ObservedObject var vm = SearchViewModel()
var body: some View {
VStack {
TextField("Type something", text: $vm.text)
.font(.title)
.padding()
.background(Color.white)
.cornerRadius(10)
.shadow(color: .gray, radius: 4, x: 0, y: 2)
HStack {
Spacer()
Button("Paste") {
vm.pasteText()
}
.buttonStyle(.borderedProminent)
Button("Clear") {
vm.clearText()
}
.buttonStyle(.borderless)
}
.padding(.top)
Spacer()
}
.padding(.horizontal)
}
}
这是 View 模型:
class SearchViewModel: ObservableObject {
@Published var text = ""
private var subscriptions = Set<AnyCancellable>()
init() {
$text
.sink(receiveValue: { value in
print("receiveValue: \(value)")
})
.store(in: &subscriptions)
}
func pasteText() {
self.text = "Text"
}
func clearText() {
self.text = ""
}
}
当我运行应用程序并输入某些内容(例如字母“A”)时,我会得到以下输出:
receiveValue:
receiveValue:
receiveValue:
receiveValue: A
receiveValue: A
创建 View 后会收到第一个空值。然后,当我专注于该字段时,会收到两个空值。最后,当我输入字母“A”时,我再次得到两个打印语句。
所以,我有几个问题:
- 当 View 刚刚出现并且尚未输入任何内容时,是否可以忽略第一个空字符串?
- 为什么当我聚焦该字段时会得到空值?
- 为什么我在输入内容后会收到重复的值?
这也很有趣,当我按下粘贴/清除按钮时,每个操作只能得到一个输出。
最佳答案
sink(receiveValue)
每次设置值时都会触发。
在您的 SearchViewModel
中,当 text
已初始化时,sink
将收到初始化值(此处 ""
).
要解决此问题,您可以使用 dropFirst()
忽略第一次更新。
关于swift - 联合收割机接收@Published更新两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76661509/