Skip to content

Instantly share code, notes, and snippets.

@satishVekariya
Created July 8, 2025 16:20
Show Gist options
  • Save satishVekariya/5e3a67abfcb5894782d41e039279ce6d to your computer and use it in GitHub Desktop.
Save satishVekariya/5e3a67abfcb5894782d41e039279ce6d to your computer and use it in GitHub Desktop.
Adds a polling task to a SwiftUI view that repeatedly performs an asynchronous action at a specified interval.
import SwiftUI
public extension View {
/// Adds a polling task to a SwiftUI view that repeatedly performs an asynchronous action at a specified interval.
///
/// This method wraps SwiftUI's `.task(id:priority:)` modifier to repeatedly invoke a given asynchronous `action`
/// until the task is cancelled. It is useful for scenarios like periodic data refreshing.
///
/// - Parameters:
/// - value: A value to identify the task. Changing this value will cancel and restart the task. Must conform to `Equatable`.
/// - interval: The time interval (in seconds) between repeated executions of the action. Evaluated as an autoclosure on each iteration.
/// - runImmediately: A Boolean value that determines whether to run the `action` immediately upon task start (`true`),
/// or wait until the first interval has passed (`false`). Defaults to `true`.
/// - priority: The task's priority. Defaults to `.userInitiated`.
/// - action: An asynchronous closure to be executed on each polling cycle. The closure must be `@Sendable`.
///
/// - Returns: A view with an attached polling task.
///
/// ### Example
/// ```swift
/// .pollingTask(
/// id: model.refreshID,
/// interval: 30,
/// runImmediately: true
/// ) {
/// await model.fetchData()
/// }
/// ```
func pollingTask<T>(
id value: T,
interval: @autoclosure @escaping () -> TimeInterval,
runImmediately: Bool = true,
priority: TaskPriority = .userInitiated,
_ action: @escaping @Sendable () async -> Void
) -> some View where T: Equatable {
self.task(id: value, priority: priority) {
repeat {
if runImmediately { await action() }
try? await Task.sleep(for: .seconds(interval()))
if !runImmediately { await action() }
} while (!Task.isCancelled)
}
}
/// Adds a polling task to a SwiftUI view that repeatedly performs an asynchronous action at a specified interval.
func pollingTask(
interval: @autoclosure @escaping () -> TimeInterval,
runImmediately: Bool = true,
priority: TaskPriority = .userInitiated,
_ action: @escaping @Sendable () async -> Void
) -> some View {
self.task(priority: priority) {
repeat {
if runImmediately { await action() }
try? await Task.sleep(for: .seconds(interval()))
if !runImmediately { await action() }
} while (!Task.isCancelled)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment