【问题标题】:Swift Combine: Alternatives too eraseToAnySubscriber?Swift Combine:擦除任何订阅者的替代方案?
【发布时间】:2019-07-26 14:22:01
【问题描述】:

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

似乎可行的是对计算变量使用 assign(),但这似乎有点 hack。


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

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

【问题讨论】:

    标签: swift subscriber combine


    【解决方案1】:

    这听起来像是 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 运算符,因为keyPaths 不是协变的:

    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)
    

    【讨论】:

    • 谢谢,很遗憾你需要借助 Objective c 来让 Swift 框架工作。
    • 好吧,您似乎想使用 KVO。如果你愿意,我可以使用 PassthroughSubject 重写它。让我颤抖吧,这只是一个例子。拿走对你有帮助的,把剩下的留给自己。
    • 我没有显示的是 hasChanged 属性是 PassthroughSubject 发布者,我很抱歉。
    • 没关系,出版商就是出版商。这就是重点。
    • 好的,改成@Published,这样我们就不依赖KVO了,希望你满意
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多