Last active
July 1, 2024 13:49
-
-
Save ipedro/9e7a20c0f240d1079a052b11fa81de33 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
import SwiftUI | |
import Combine | |
typealias BindableObservableObject<T> = T where T: ObservableObject, T.ObjectWillChangePublisher == ObservableObjectPublisher | |
/// A type that exposes its writable properties as bindings. | |
extension ObservableObject where Self == BindableObservableObject<Self> { | |
/// A type that acts as a lens that exposes bindings to the | |
/// writable properties of this type. | |
typealias Bindings = ExposedBindings<Self> | |
/// A lens that exposes bindings to the writable properties | |
/// of this instance. | |
@MainActor | |
var bindings: Bindings { | |
Bindings(base: self) | |
} | |
} | |
/// A type that acts as a lens that exposes bindings to the | |
/// writable properties of a base object. | |
@dynamicMemberLookup | |
struct ExposedBindings<Base> where Base == BindableObservableObject<Base> { | |
/// The base object whose bindings are exposed. | |
fileprivate let base: Base | |
/// Returns a binding to the property at the given key path. | |
subscript<Value>(dynamicMember keyPath: ReferenceWritableKeyPath<Base, Value>) -> Binding<Value> { | |
Binding { | |
base[keyPath: keyPath] | |
} set: { | |
base[keyPath: keyPath] = $0 | |
base.objectWillChange.send() | |
} | |
} | |
/// Returns a lens that exposes the bindings of the object | |
/// at the given key path. | |
subscript<T>(dynamicMember keyPath: KeyPath<Base, T>) -> ExposedBindings<T> where T == BindableObservableObject<T> { | |
ExposedBindings<T>(base: base[keyPath: keyPath]) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment