Skip to content

Instantly share code, notes, and snippets.

@lukepistrol
Created April 10, 2023 08:25
Show Gist options
  • Save lukepistrol/4335dc0a589f5273d2b5ea951797207d to your computer and use it in GitHub Desktop.
Save lukepistrol/4335dc0a589f5273d2b5ea951797207d to your computer and use it in GitHub Desktop.
Provides a task modifier with an optional binding that will run the task if the binding is set to a non-nil value and reset it to nil once the task is done. The purpose of this is to bind a one-shot task to the view, i.e. the cancellation is automatically performed if the view should be dismissed.
/// Provides a task modifier with an optional binding that will run the task if the binding is set to a
/// non-nil value and reset it to nil once the task is done.
///
/// The purpose of this is to bind a one-shot task to the view, i.e. the cancellation is automatically
/// performed if the view should be dismissed.
struct TaskViewModifier<T: Equatable>: ViewModifier {
@Binding var taskId: T?
let action: @Sendable (_: T) async -> Void
func body(content: Content) -> some View {
ZStack {
content
.task(id: taskId) {
guard let taskId = taskId else {
return
}
await action(taskId)
self.taskId = nil
}
}
}
}
public extension View {
/// Provides a task modifier with an optional binding that will run the task if the binding is set to a
/// non-nil value and reset it to nil once the task is done.
///
/// The purpose of this is to bind a one-shot task to the view, i.e. the cancellation is automatically
/// performed if the view should be dismissed.
///
/// - Parameters:
/// - taskId: A binding to an optional `T` that will trigger the task when set to a non-nil value.
/// - action: The async action to perform.
func task<T: Equatable>(_ value: Binding<T?>, _ action: @escaping @Sendable (_: T) async -> Void) -> some View {
modifier(TaskViewModifier<T>(taskId: value, action: action))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment