这听起来像是 CombineLatest 的工作。是的,这sink
是一种以您喜欢的方式处理管道末端的完美方式。
这是一个简单的例子。我将从具有 、 和 变量的r
对象g
开始b
:
class ColorObject {
@Published var r : CGFloat = 1
@Published var g : CGFloat = 1
@Published var b : CGFloat = 1
}
现在想象在某处我们有该对象的一个实例;叫它colorObject
。然后我们可以配置一个发布者:
let rpub = colorObject.$r
let gpub = colorObject.$g
let bpub = colorObject.$b
let colorpub = Publishers.CombineLatest3(rpub,gpub,bpub)
.map { UIColor(red: $0.0, green: $0.1, blue: $0.2, alpha: 1) }
结果是每次colorObject
'r
或g
或b
改变时,UIColor 都会从管道中下来。colorpub
现在我们可以通过订阅它来接收通知,sink
并按照我们喜欢的方式处理结果。让我们将一些界面对象的颜色设置为该颜色:
let sink = colorpub.sink { self.view.backgroundColor = $0 }
或者,我可以使用 来编写它assign
,这可能更干净,但backgroundColor
它是一个 Optional ,所以我必须插入一个map
运算符,因为 keyPaths 不是协变的:
let assign = colorpub.map{Optional($0)}
.assign(to: \.backgroundColor, on: self.view)
现在,每当colorObject
' r
、g
或b
变化时,我们视图的颜色都会相应变化。
这不是实现这一目标的唯一方法——远非如此!但这是使用 Combine 完成任务的一个简单示例。一个可能有用的变体是将colorpub
发布者向上移动到 ColorObject 中;这样,ColorObject 本身就直接提供颜色:
class ColorObject {
@Published var r : CGFloat = 1
@Published var g : CGFloat = 1
@Published var b : CGFloat = 1
lazy var colorpub = Publishers.CombineLatest3($r,$g,$b)
.map { UIColor(red: $0.0, green: $0.1, blue: $0.2, alpha: 1) }
}
这不会改变sink
or assign
:
let sink = colorObject.colorpub.sink { // ... whatever
// or
let assign = colorObject.colorpub.map{Optional($0)}
.assign(to: \.backgroundColor, on: self.view)