Skip to content

Instantly share code, notes, and snippets.

@IanKeen
Created June 27, 2020 20:24
Show Gist options
  • Select an option

  • Save IanKeen/d78e3a1a22e762f62b3eba9ad3bdcc28 to your computer and use it in GitHub Desktop.

Select an option

Save IanKeen/d78e3a1a22e762f62b3eba9ad3bdcc28 to your computer and use it in GitHub Desktop.
PropertyWrapper: Delegate updates similar to SwiftUIs ObservableObject/Published combo
public protocol DelegateProvider: AnyObject {
static func notifyDelegate(_ instance: Self)
}
@propertyWrapper
public struct Delegate<Value> {
public var wrappedValue: Value
public init(wrappedValue: Value) {
self.wrappedValue = wrappedValue
}
public static subscript<Instance: DelegateProvider>(
_enclosingInstance instance: Instance,
wrapped wrappedKeyPath: ReferenceWritableKeyPath<Instance, Value>,
storage storageKeyPath: ReferenceWritableKeyPath<Instance, Self>
) -> Value {
get {
return instance[keyPath: storageKeyPath].wrappedValue
}
set {
instance[keyPath: storageKeyPath].wrappedValue = newValue
Instance.notifyDelegate(instance)
}
}
}
// Updating any of the properties marked `@Delegate` will notify the delegate
protocol ViewModelDelegate: AnyObject {
func viewModelUpdated(_ viewModel: ViewModel)
}
class ViewModel: DelegateProvider {
static func notifyDelegate(_ instance: ViewModel) {
instance.delegate?.viewModelUpdated(instance)
}
@Delegate private(set) var foo: Int = 0
@Delegate private(set) var bar: String = ""
@Delegate private(set) var baz: [Bool] = []
weak var delegate: ViewModelDelegate? { // property wrappers dont work with `weak` :(
didSet { Self.notifyDelegate(self) }
}
init() { }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment