简体   繁体   中英

Swift Combine doesn't update value by sink

I want to achieve this: A class A , which has a property var c1: C and var b1: B , if the property of C changes, then the property of b1 should be updated.

Here is my code:

import UIKit
import Combine

struct B {
    var b = "b"
}

class C: ObservableObject {
    @Published var c: String = "c1"
}

class A: ObservableObject {
    var b1 = B()
    var cancellables = Set<AnyCancellable>()
    @Published var c1 = C()

    init() {

        $c1.sink {
            print("new value is \($0.c)") //Only print once
            self.b1.b = $0.c
        }.store(in: &cancellables)
    }

    func printMe() {
        print("b1.b: \(b1.b)")
        print("c1.c: \(c1.c)")
    }
}



let a = A()
a.c1.c = "c2"
a.printMe()


a.c1.c = "c3"
a.printMe()

The output is:

new value is c1
b1.b: c1
c1.c: c2
b1.b: c1
c1.c: c3

Every time the a.c1.c was updated I expected a.b1.b should be updated automatically by sink , not sure if anything I missed, the sink closure body just was called once.

Any suggestion? thanks!

With @Published var c1 = C() and $c1.sink you are observing changes to A 's property c1 . This assignment does not change, since it is a reference type, so the sink is only called on initialisation.

Updating the sink to:

c1.$c.sink {
    print("new value is \($0)") //Prints every time! 
        self.b1.b = $0
    }.store(in: &cancellables)

Gives the behaviour you're looking for. I don't think the c1 publisher will emit any values in this scenario, but it's not clear what behaviour you're looking for there so I haven't gone into it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM