27

I am using a timer in a SwiftUI view as in code below. It works as expected BUT under some conditions I want to cancel/stop that timer. There seems to be no ".cancel" property or method on the timer var. How do I cancel this timer? Any ideas/tips?


import SwiftUI

struct ContentView: View {

    @State private var selection = 2

    @State private var rotation: Double = GBstrtest

    let timer = Timer.publish (every: 0.8, on: .current, in: .common).autoconnect()

    var body: some View {
        TabView(selection: $selection){
            Text("Settings")
                .font(.title)
                .tabItem {
                    VStack {
                        Image(systemName: "gear")
                        .font(Font.system(.title ))
                        Text("Settings")
                    }
                }
                .tag(0)
            VStack {
                Divider().padding(2)
                ZStack {
                    Image("image1")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                    Image("image2")
                        .resizable()
                        .aspectRatio(contentMode:.fit)
                        .rotationEffect(.degrees(rotation))
                        .animation(.easeInOut(duration: 0.3) )
                        .padding(EdgeInsets(top: 0, leading: 50, bottom: 0, trailing: 50))
              }
              Spacer()
            }
            .tabItem {
                VStack {
                    Image(systemName: "speedometer")
                        .font(Font.system(.title ))
                    Text("Read Meter")
                }
            }
            .tag(1)
        }
        .onReceive(timer) {
            _ in self.rotation = Double.random(in: 0 ... 200)
            // How do I cancel timer HERE!?
        }
    }
}

2 Answers 2

68

Inside your conditional statement, use the following code:

self.timer.upstream.connect().cancel()
Sign up to request clarification or add additional context in comments.

5 Comments

how to reconnect? @RazibMollick
self.timer.upstream.autoconnect()
Yes to reconnect timer.upstream.autoconnect() works but your timer most likely should be a @State var since it is being reinitialized. If you used a 'let' for your timer like I was doing, autoconnect() won't work. Hope this helps.
on reconnect it showing this warning Result of call to 'autoconnect()' is unused
For me timer.upstream.autoconnect() doesn't work even if it's declaired as @State private var timer ...
22

Full cycle goes like this:

struct MySwiftUIView : View {
...

@State var timer = Timer.publish (every: 1, on: .current, in: .common).autoconnect()
@State var timeRemaining = -1

var body: some View {
    ZStack {
       // Underlying shapes etc as needed

       Text("\(timeRemaining)").
           .opacity(timeRemaining > 0 ? 1 : 0)
           .onReceive(timer) { _ in
                if self.timeRemaining < 0 {
                    // We don't need it when we start off
                    self.timer.upstream.connect().cancel()
                    return
                }
                if self.timeRemaining > 0 {
                    self.timeRemaining -= 1
                } else {
                    self.timer.upstream.connect().cancel()
                    // Do the action on end of timer. Text would have been hidden by now
                }
          }
          .onTapGesture {  // Or any other event handler that should start countdown
                self.timeRemaining = Int(delayValue)
                self.timer = Timer.publish (every: 1, on: .current, in: 
                                                   .common).autoconnect()
          }
    }

Voila! A reusable timer, use it as many times as you'd like!

1 Comment

How can we achieve the same but with the logic and timer in ViewModel ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.