Swift Combine:替代品也擦除到任何订阅者?



我正在尝试使用组合来更新颜色,当我的红色、绿色或蓝色变量发生变化时。我看过的例子使用 sink(),这对我来说似乎很合适,但 eraseToAnySubscriber 是 MIA,我找不到替代品。

似乎有效的方法是对计算变量使用 assign(),但这似乎有点黑客。


init() {
redCancellable = red.hasChanged.receive(on: RunLoop.main).assign(to: .rgbUpdated, on: self)
}

有没有办法保存 sink() 返回的值?

这听起来像是CombineLatest的工作。是的,sink是以您喜欢的任何方式处理管道末端的完美方法。

下面是一个简单的示例。我将从一个具有rgb变量的对象开始:

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) }

结果是,每当colorObjectrgb更改时,UIColor 就会沿着管道向下移动。现在,我们可以通过sink订阅colorpub来接收来自的通知,并按照我们喜欢的方式处理结果。让我们将某个界面对象的颜色设置为该颜色:

let sink = colorpub.sink { self.view.backgroundColor = $0 }

或者,我可以使用assign编写它,这可能更干净,尽管backgroundColor是可选的,所以我必须插入一个map运算符,因为 keyPath 不是协变的:

let assign = colorpub.map{Optional($0)}
.assign(to: .backgroundColor, on: self.view)

现在,每当colorObjectrgb发生变化时,我们视图的颜色也会随之改变。

这不是实现这一目标的唯一途径——远非如此!但这是使用 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) }
}

这不会改变sinkassign

let sink = colorObject.colorpub.sink { // ... whatever
// or
let assign = colorObject.colorpub.map{Optional($0)}
.assign(to: .backgroundColor, on: self.view)

相关内容

  • 没有找到相关文章

最新更新