Skip to content

Instantly share code, notes, and snippets.

@JadenGeller
Created October 31, 2023 17:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JadenGeller/f01f6963c171a4cbad6a4cc526857376 to your computer and use it in GitHub Desktop.
Save JadenGeller/f01f6963c171a4cbad6a4cc526857376 to your computer and use it in GitHub Desktop.
Async view for awaiting tasks
import SwiftUI
protocol DeferedTask {
associatedtype Success
func run() async throws -> Success
}
struct ResultView<T: DeferedTask, ID: Equatable, Content: View>: View {
var task: T
var id: KeyPath<T, ID>
var priority: TaskPriority = .userInitiated
@ViewBuilder var content: (Result<T.Success, Error>?) -> Content
@State var result: Result<T.Success, Error>? = nil
var body: some View {
content(result)
.task(id: task[keyPath: id], priority: priority) {
do {
result = .success(try await task.run())
} catch let error {
result = .failure(error)
}
}
}
}
extension ResultView where T: Identifiable, T.ID == ID {
init(task: T, priority: TaskPriority = .userInitiated, @ViewBuilder content: @escaping (Result<T.Success, Error>?) -> Content) {
self.init(task: task, id: \.id, priority: priority, content: content)
}
}
protocol AsyncView: DeferedTask {
associatedtype Body: View
@ViewBuilder var body: Body { get async }
}
extension AsyncView {
func run() async throws -> Body {
await body
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment