|
import SwiftUI |
|
|
|
struct UnwrappingButton<Label: View, T>: View { |
|
|
|
enum Unwrapping<T> { |
|
case element(value: T?, action: (T) -> Void) |
|
case binding(value: Binding<T?>, action: (Binding<T>) -> Void) |
|
|
|
var value: T? { |
|
switch self { |
|
case .element(let value, _): |
|
return value |
|
case .binding(let value, _): |
|
return value.wrappedValue |
|
} |
|
} |
|
|
|
func run() { |
|
switch self { |
|
case .element(let value, let action): |
|
if let value = value { |
|
action(value) |
|
} |
|
case .binding(let value, let action): |
|
if let value = Binding(value) { |
|
action(value) |
|
} |
|
} |
|
} |
|
} |
|
|
|
let unwrapping: Unwrapping<T> |
|
@ViewBuilder let label: Label |
|
|
|
init(element: T?, action: @escaping (T) -> Void, @ViewBuilder label: () -> Label) { |
|
self.unwrapping = .element(value: element, action: action) |
|
self.label = label() |
|
} |
|
|
|
init(element: Binding<T?>, action: @escaping (Binding<T>) -> Void, @ViewBuilder label: () -> Label) { |
|
self.unwrapping = .binding(value: element, action: action) |
|
self.label = label() |
|
} |
|
|
|
var body: some View { |
|
Button { |
|
unwrapping.run() |
|
} label: { |
|
label |
|
} |
|
.disabled(unwrapping.value == nil) |
|
} |
|
} |
|
|
|
extension UnwrappingButton where Label == Text { |
|
init(element: T?, title: String, action: @escaping (T) -> Void) { |
|
self.unwrapping = .element(value: element, action: action) |
|
self.label = Text(title) |
|
} |
|
|
|
init(element: Binding<T?>, title: String, action: @escaping (Binding<T>) -> Void) { |
|
self.unwrapping = .binding(value: element, action: action) |
|
self.label = Text(title) |
|
} |
|
} |