0

I'm new in the Combine world and i have var timer: AnyPublisher<Date,Never> to 're-use' the timer i have in the ContentView for my SecondView, do i have to invalidate/cancel the timer when i no longer need it? If yes, how to do it?

In the previous code with a timer of type Timer.TimerPublisher if i had to cancel it I did it using: timer.upstream.connect().cancel() and now of course it keeps giving me this error: Value of type 'AnyPublisher<Date, Never>' has no member 'upstream'

Asperi
  • 228,894
  • 20
  • 464
  • 690
simonaus
  • 43
  • 5
  • Please have a look at https://developer.apple.com/documentation/combine/replacing-foundation-timers-with-timer-publishers – vadian Aug 19 '22 at 09:55
  • If i got it right, it says that it autoconnects and autodisconnect automatically? So i don't need to cancel it @vadian – simonaus Aug 19 '22 at 10:31
  • Just remove/cancel subscriber(s), with no subscription publisher is canceled automatically. Example https://stackoverflow.com/a/64421357/12299030 or https://stackoverflow.com/a/62476194/12299030 or https://stackoverflow.com/a/61540669/12299030. – Asperi Aug 19 '22 at 11:20
  • Why reuse the timer? Let SecondView create its own timer. – vacawama Aug 19 '22 at 11:41
  • @vacawama How to create more than one timer? I tried to do it but if i already have a timer the second one doesn't work – simonaus Aug 19 '22 at 12:45
  • Just assign each timer to its own variable. – vacawama Aug 19 '22 at 16:16
  • @vacawama Did it, my timers had 2 different variables but didn't work – simonaus Aug 19 '22 at 16:57
  • Without source code, its hard to know where you're going wrong. I just created a list with 20 different timers running all in the same View. If you're still curious about this, post the code you tried in a new question, and I'm sure someone can point out your issue. – vacawama Aug 19 '22 at 17:25

1 Answers1

0

Maybe something like this can help?

private var timerSubscription: AnyCancellable?

func setupTimer(every interval: TimeInterval, repeats: Bool, onReceive: @escaping (() -> Void)) {
    invalidateTimer()

    timerSubscription = Timer
        .publish(every: interval, on: .main, in: .common)
        .autoconnect()
        .sink { _ in
            onReceive()
            if !repeats {
                self.invalidateTimer()
            }
        }
}

func invalidateTimer() {
    timerSubscription?.cancel()
}

full service:

final class CombineTimerService {

// MARK: - Public Properties

var isCancelled: Bool {
    return timerSubscription == nil
}

// MARK: - Private Properties

private var timerSubscription: AnyCancellable?
private var onReceive: (() -> Void)?

// MARK: - Public

func setupTimer(every interval: TimeInterval, repeats: Bool, onReceive: @escaping (() -> Void)) {
    invalidateTimer()
    self.onReceive = onReceive

    timerSubscription = Timer
        .publish(every: interval, on: .main, in: .common)
        .autoconnect()
        .sink { _ in
            onReceive()
            if !repeats {
                self.invalidateTimer()
            }
        }
}

func invalidateTimer() {
    timerSubscription?.cancel()
    onReceive = nil
}

func fire() {
    onReceive?()
}
}
Mike H
  • 487
  • 2
  • 13
  • On timerSubscription = Timer.publish it says 'Cannot assign to property: 'self' is immutable' – simonaus Aug 19 '22 at 10:44
  • I assume your'e using timer in struct. You can wrap timer in a class so you won't get such error. I sent a full class above :) – Mike H Aug 19 '22 at 10:49