Is there a way to create a SwiftUI Binding
from a computed property that provides a get {}
and set {}
shorthand?
Creating bindings for existing read-write properties seems unnessecarily complicated and verbose:
extension UserDefaults {
var isTrackingEnabled: Bool {
get { bool(forKey: "isTrackingEnabled") }
set { set(newValue, forKey: "foo") }
}
}
struct TrackingView: View {
@Binding private var isTrackingEnabled: Bool
init(defaults: UserDefaults) {
self._isTrackingEnabled = Binding(
get: { defaults.isTrackingEnabled },
set: { newValue in defaults.isTrackingEnabled = newValue }
)
}
...
}
I am aware that this specific example is already solved in SwiftUI with the @AppStorage
property wrapper, I am rather looking to emulate the same behaviour in general without having to create too much boilerplate.
I am looking to create the following syntax: UserDefaults.standard.$isTrackingEnabled
where the property wrapper's projected value can be used as well as the wrapped value but wrapping the property directly is forbidden:
extension UserDefaults {
@Binding var isTrackingEnabled: Bool { // ❌ Non-static property 'isTrackingEnabled' declared inside an extension cannot have a wrapper
Binding(
get: { bool(forKey: "isTrackingEnabled") },
set: { newValue in set(newValue, forKey: "foo") }
)
}
}
Could one create a macro to convert between the two get-set representations?