I'm following this example: https://www.swiftbysundell.com/basics/combine/ (modified it a bit) and it prints 1, 2, 3, as I expect.
class MyCounter {
var publisher: AnyPublisher<Int, Never> {
subject.eraseToAnyPublisher()
}
private(set) var value = 0 {
didSet { subject.send(value) }
}
private let subject = PassthroughSubject<Int, Never>()
func increment() {
value += 1
}
}
class PrintCounter {
let myCounter = MyCounter()
init() {
let cancellable = myCounter.publisher
.sink { value in
print(value)
}
myCounter.increment()
myCounter.increment()
myCounter.increment()
}
}
let printCounter = PrintCounter()
I am now trying to publish other values, Timer, Location coordinates, etc, and am not successful yet.
class MyTimer {
var subscriptions = Set<AnyCancellable>()
var publisher: AnyPublisher<Int, Never> {
subject.eraseToAnyPublisher()
}
private var value = 0 {
didSet {
subject.send(value)
}
}
private let subject = PassthroughSubject<Int, Never>()
init() {
let currentDate = Date()
Timer.publish(every: 1.0, on: .main, in: .common)
.autoconnect()
.map({ (output) in
return output.timeIntervalSince(currentDate)
})
.map({ (timeInterval) in
return Int(timeInterval)
})
.sink { (seconds) in
print("MyTimer: \(seconds)")
self.value = seconds
}
.store(in: &subscriptions)
}
}
class PrintMyTimer {
let myTimer = MyTimer()
init() {
let cancellable = myTimer.publisher
.sink { value in
print("PrintMyTimer: \(value)")
}
}
}
let printMyTimer = PrintMyTimer()
Even though 'value' increments in MyTimer it's not showing in printMyTimer sink (print statement).
So I'm just wondering if I'm on the right track to be using Combine for this purpose to begin with.
Whether Combine is the best approach to this sort of problem is a bit subjective. Some people will say that the new async sequences are the future. But Combine works well, especially when there are multiple subscribers.
The reason your example does not work is because the subscription goes out of scope when PrintMyTimer
’s initialiser is finished. That automatically cancels the subscription. Just like in MyTimer
, you need to save the subscription to keep it alive:
class PrintMyTimer {
var subscriptions = Set<AnyCancellable>()
let myTimer = MyTimer()
init() {
myTimer.publisher
.sink { value in
print("PrintMyTimer: \(value)")
}
.store(in: &subscriptions)
}
}