swift - 联合收割机接收@Published更新两次

标签 swift swiftui combine

我目前正在构建一个搜索字段,当其值发生变化时应该执行一些操作。这是我的观点:

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”时,我再次得到两个打印语句。

所以,我有几个问题:

  1. 当 View 刚刚出现并且尚未输入任何内容时,是否可以忽略第一个空字符串?
  2. 为什么当我聚焦该字段时会得到空值?
  3. 为什么我在输入内容后会收到重复的值?

这也很有趣,当我按下粘贴/清除按钮时,每个操作只能得到一个输出。

最佳答案

sink(receiveValue) 每次设置值时都会触发。

在您的 SearchViewModel 中,当 text 已初始化时,sink 将收到初始化值(此处 "").

要解决此问题,您可以使用 dropFirst() 忽略第一次更新。

关于swift - 联合收割机接收@Published更新两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76661509/

相关文章:

swift - 单击键盘中的返回键时 UITextField 如何移动到下一个 TextField

未保存整数的 IOS Swift 值

ios - 修复导航栏

ios - 在 iOS 9.3/Xcode 7.3 中使用 StoreKit 常量时使用未解析的标识符

ios - SwiftUI 截断某些字母的文本

SwiftUI:关闭 macOS NavigationView 中的 View

swift - 如何在 SwiftUI 中给 DatePicker 一个分钟间隔

swift - Swift 中 `Combine` 和 `didSet` 有什么区别?

swift - 如何使用 Combine 遍历发布者的输出?

iOS 组合 : get a strongly typed error from URLSession's dataTaskPublisher