How to have a view dismiss itself via timer in SwiftUI?

This question is more about SwiftUI, rather than the language itself. I'd advise that other questions like this are asked over Apple Developer Forums instead.


You're using the same timer across the views, and the code seems to have some timing problem. Namely, the timer is not yet invalidated when a new view appears, so the interval is immediately negative. I think moving self.timerManager.start() to onDisappear should be good enough.

Or you can just do something like this:

struct CountDownIntervalView: View {
    @Environment(\.presentationMode) var mode
    @State var remaining = 4.0
    
    var body: some View {
        VStack {
            Text("Time remaining: \(remaining, specifier: "%.2f")")
            Button("Quit early!") {
                self.mode.wrappedValue.dismiss()
            }
        }
        .navigationBarBackButtonHidden(true)
        .onReceive(Timer.publish(every: 0.01, on: .current, in: .default).autoconnect()) { _ in
            self.remaining -= 0.01
            if self.remaining <= 0 {
                self.mode.wrappedValue.dismiss()
            }
        }
    }
}

Note: you can just use "\(interval, specifier: "%.2f")" on Text.

3 Likes