Swift 组合接收器在设置时调用一次?

Swift Combine sink called once at setup?

我正在设置 sink 像这样:

    name.publisher
        .removeDuplicates()
        .receive(on: RunLoop.main)
        .sink { [weak self] config in
            guard let self = self else { return }

            // this closure gets called right away at setup even though the @Published property `name` was already setup and did not change
            
        }.store(in: &subscribers)

属性 在可观察对象中的声明方式如下:

 @Published var name:String = ""

所以,我显然在这里遗漏了一些东西。为什么即使 name 没有改变,在设置时也会调用 sink 一次?我可以通过使用 dropFirst() 运算符来避免这种行为,但是,我想了解为什么总是在设置后立即调用一次闭包?

这是为什么?

这是一个使用 debugPrint 向您展示从 name.publisher 获得的内容的游乐场:

import UIKit
import Combine

//Holds the score
class ViewModel : ObservableObject {
    @Published var name = "0"
}

let viewModel = ViewModel()
debugPrint(viewModel.name.publisher)

你得到的是

Combine.Publishers.Sequence<Swift.String, Swift.Never>(sequence: "0")

所以你得到一个序列发布者,它有一个项目,“0”。它将发布一次该值,然后序列将结束。每次订阅者附加到该序列时,它将获得序列中的所有项目(只有一个)和结尾。

这可能不是你想要的。

相反,我认为您想使用 $name 访问已发布的 属性:

import UIKit
import Combine

//Holds the score
class ViewModel : ObservableObject {
    @Published var name = "0"
}

let viewModel = ViewModel()
let subscription = viewModel.$name.sink { print([=11=]) }
viewModel.name = "Alex"

当您订阅已发布的 属性 时,您仍然会收到一个已发布的事件,该事件是 属性 的当前值。但是,通过使用 $name 您将附加到一个流,该流将向您发送订阅的当前值和每个后续值。