๐Ÿ‘”TimerView (scheduledTimer)

Combine โŸฉ Timer โŸฉ TimerView (scheduledTimer)

// 2022.03.25: (*) use Timer.scheduledTimer()

import SwiftUI
import Combine

/// ๐Ÿ‘” TimerView (Timer.scheduledTimer)
/// ```
/// TimerView { ... }
/// TimerView(every: 2) { ... }
/// TimerView(every: 3, update: { timer in ... }) { ... }
/// ```
struct TimerView<Content: View>: View {
    
    // โญ๏ธ # of seconds between firings of timer
    let interval: TimeInterval
    
    // โญ๏ธ timer event handler
    let update: (Timer) -> Void
    
    // โญ๏ธ generate timer content
    @ViewBuilder var content: () -> Content 
        
    // init
    init(
        every interval: TimeInterval = 1, 
        update: @escaping (Timer) -> Void = {_ in},     // default: do nothing
        @ViewBuilder content: @escaping () -> Content
    ) {
        self.interval = interval
        self.content = content
        self.update = update
    }
    
    // โญ๏ธ detect whether app has gone background
    @Environment(\.scenePhase) private var scenePhase
    @State private var isActive = true
    
    var body: some View {
        content()
            .onAppear {
                // โญ๏ธ scheduled timer
                Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { timer in 
                    // โญ๏ธ if app goes background, stop updating immediately.
                    guard isActive else { return }
                    update(timer)
                }
            }
            // โญ๏ธ mark the app inactive once it goes background.
            .onChange(of: scenePhase) { newPhase in
                isActive = (newPhase == .active)
            }
    }
}

Last updated