Last active
January 14, 2022 18:15
-
-
Save magnuskahr/5dbe493a1b551db9afa2ab2e61c345eb to your computer and use it in GitHub Desktop.
A SwiftUI toggle to switch on/off a value for an optional state
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct ValueToggle<Value, Label: View>: View { | |
@Binding var value: Value? | |
let onValue: Value | |
let label: () -> Label | |
@State private var isOn = false | |
var body: some View { | |
Toggle(isOn: $isOn, label: label) | |
.onAppear { | |
isOn = (value != nil) | |
} | |
.onChange(of: isOn) { | |
value = $0 ? onValue : nil | |
} | |
} | |
} | |
extension ValueToggle where Label == Text { | |
internal init(value: Binding<Value?>, onValue: Value, label: String) { | |
self._value = value | |
self.onValue = onValue | |
self.label = { Text(label) } | |
} | |
} |
Hey @smic, that is a great idea and totally valid as well!
However I think that ValueToggle reads better and conveys the meaning easier, but that is just me - thanks for your input!
.... though your suggestion did make me think; it could also be an extension on Toggle it self!
extension Toggle where Label == Text {
public init<Value>(_ titleKey: LocalizedStringKey, for value: Binding<Value?>, default defaultValue: Value) {
self.init(titleKey, isOn: Self.binding(value, default: defaultValue))
}
public init<Value, S: StringProtocol>(_ title: S, for value: Binding<Value?>, default defaultValue: Value) {
self.init(title, isOn: Self.binding(value, default: defaultValue))
}
}
extension Toggle {
public init<Value>(for value: Binding<Value?>, default defaultValue: Value, @ViewBuilder label: () -> Label) {
self.init(isOn: Self.binding(value, default: defaultValue), label: label)
}
private static func binding<Value>(_ value: Binding<Value?>, default defaultValue: Value) -> Binding<Bool> {
Binding {
value.wrappedValue != nil
} set: { newValue in
value.wrappedValue = newValue ? defaultValue: nil
}
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Wouldn't it be easier to write a custom binding like