Skip to content

Instantly share code, notes, and snippets.

@ole
Last active September 26, 2025 13:20
Show Gist options
  • Save ole/6e3752865319498504871982032d76af to your computer and use it in GitHub Desktop.
Save ole/6e3752865319498504871982032d76af to your computer and use it in GitHub Desktop.
/// Runs a secondary side action concurrently with a primary action.
/// The secondary action only starts after the specified delay.
///
/// Usage example: showing a progress indicator UI only if the primary action
/// takes a significant amount of time.
///
/// The secondary action runs in a child task (structured concurrency).
///
/// - Note: I'd like to provide a default argument for the clock: `clock: C = .continuous`,
/// like `Task.sleep` does. But this doesn't compile in Swift 6.2. Related bug report:
/// [swiftlang/swift issue #67680: Default expression for inference works for static methods but not functions](https://github.com/swiftlang/swift/issues/67680)
@available(macOS 15.0, *)
nonisolated(nonsending)
public func withSideActionAfterDelay<Return, Failure: Error, C: Clock>(
delay: C.Instant.Duration,
clock: C,
_ primary: () async throws(Failure) -> Return,
delayedAction: sending () async -> Void
) async throws (Failure) -> Return {
#if compiler(>=6.3)
#warning("Check if 'clock: C = .continuous' is supported now. See https://github.com/swiftlang/swift/issues/67680")
#endif
async let _ = {
try? await Task.sleep(for: delay, clock: clock)
if !Task.isCancelled {
await delayedAction()
}
}()
return try await primary()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment