Skip to content

Instantly share code, notes, and snippets.

@schwa
Created February 18, 2021 17:07
Show Gist options
  • Save schwa/48e4cb47279afa66090d858b1c3e997a to your computer and use it in GitHub Desktop.
Save schwa/48e4cb47279afa66090d858b1c3e997a to your computer and use it in GitHub Desktop.
struct ErrorHandler {
var callback: (Error) -> Void
func handle(_ block: () throws -> Void) {
do {
try block()
}
catch {
callback(error)
}
}
}
struct ErrorHandlerKey: EnvironmentKey {
static var defaultValue = ErrorHandler {
fatalError("Unhandled error: \($0)")
}
}
extension EnvironmentValues {
var errorHandler: ErrorHandler {
get {
self[ErrorHandlerKey.self]
}
set {
self[ErrorHandlerKey.self] = newValue
}
}
}
struct ErrorHandlingView <Content>: View where Content: View {
let content: () -> Content
@State
var error: Error?
@State
var isPresented: Bool = false
var body: some View {
content().environment(\.errorHandler, ErrorHandler() {
self.error = $0
self.isPresented = true
})
.alert(isPresented: $isPresented, content: {
guard let error = error else {
fatalError("Ironically our error handler had an error.")
}
return Alert(title: Text("Error"), message: Text("\(String(describing: error))"), dismissButton: .default(Text("That sucks")))
})
}
}
//////
struct ContentView: View {
var body: some View {
ErrorHandlingView() {
PretendThisViewIsDeeplyBuriedInApp()
}
}
}
struct PretendThisViewIsDeeplyBuriedInApp: View {
@Environment(\.errorHandler)
var errorHandler
var body: some View {
Button("Crash") {
errorHandler.handle {
throw MyError()
}
}
}
}
@schwa
Copy link
Author

schwa commented Feb 18, 2021

For bonus points look to get rid of ErrorHandler and just have the environment value be a closure that takes a throwing closure… This would give you:

struct PretendThisViewIsDeeplyBuriedInApp: View {
    @Environment(\.errorHandler)
    var errorHandler

    var body: some View {
        Button("Crash") {
            errorHandler {
                throw MyError()
            }
        }
    }
}```

There is some (minor) value to the explicit ErrorHandler type though (for example a method that just takes an error without having to provide a closure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment