Skip to content

Instantly share code, notes, and snippets.

@evandcoleman
Created December 30, 2022 21:37
Show Gist options
  • Save evandcoleman/59ebca65bf476093912f4385489e385d to your computer and use it in GitHub Desktop.
Save evandcoleman/59ebca65bf476093912f4385489e385d to your computer and use it in GitHub Desktop.
Super simple error handling in SwiftUI
//
// HandleErrors.swift
// App
//
// Created by Evan Coleman on 12/30/22.
//
import SwiftUI
// MARK: Usage Example/Preview
struct HandleErrorViewModifier_Previews: PreviewProvider {
static var previews: some View {
ErroringView()
.handleErrors()
}
struct ErroringView: View {
@Environment(\.handleError) var handleError
var body: some View {
Button("Trigger Error", action: { handleError(Error()) })
}
struct Error: LocalizedError {
var errorDescription: String? = "This is a test error"
}
}
}
// MARK: HandleErrorAction
private struct HandleErrorKey: EnvironmentKey {
static let defaultValue: HandleErrorAction = .init(handler: { _ in })
}
extension EnvironmentValues {
var handleError: HandleErrorAction {
get { self[HandleErrorKey.self] }
set { self[HandleErrorKey.self] = newValue }
}
}
struct HandleErrorAction {
var handler: (Error) -> Void
func callAsFunction(_ error: Error) {
handler(error)
}
}
// MARK: HandleErrorViewModifier
extension View {
func handleErrors() -> some View {
modifier(HandleErrorViewModifier())
}
}
struct HandleErrorViewModifier: ViewModifier {
@State var currentError: Error?
private var isPresented: Binding<Bool> {
.init(
get: { currentError != nil },
set: { newValue in
if !newValue {
currentError = nil
}
}
)
}
func body(content: Content) -> some View {
content
.alert("Oh no!", isPresented: isPresented, actions: {
Button(action: { currentError = nil }) {
Text("Dismiss")
}
}, message: {
Text(currentError?.localizedDescription ?? "")
})
.environment(\.handleError, HandleErrorAction { error in
currentError = error
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment