Skip to content

Instantly share code, notes, and snippets.

@DevAndArtist
Last active February 9, 2024 13:28
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save DevAndArtist/ad6c438fef9e94b743038da93b50e1a2 to your computer and use it in GitHub Desktop.
Save DevAndArtist/ad6c438fef9e94b743038da93b50e1a2 to your computer and use it in GitHub Desktop.
import Combine
import SwiftUI
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
@propertyWrapper
public struct Model<Value>: DynamicProperty {
final class _Box: ObservableObject {
let objectWillChange = ObservableObjectPublisher()
var value: Value {
willSet {
objectWillChange.send()
}
}
init(value: Value) {
self.value = value
}
}
let _subscription: AnyCancellable?
@ObservedObject
var _box: _Box
public init(wrappedValue value: Value) {
self._subscription = .none
self._box = _Box(value: value)
}
public init<T>(
publisher: T,
defaultValue: Value
) where T: Publisher, T.Output == Value, T.Failure == Never {
let box = _Box(value: defaultValue)
self._subscription = publisher.assign(to: \.value, on: box)
self._box = box
}
public var wrappedValue: Value {
get {
_box.value
}
nonmutating set {
_box.value = newValue
}
}
public var projectedValue: Binding<Value> {
$_box.value
}
public mutating func update() {
__box.update()
}
}
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension Model where Value: ExpressibleByNilLiteral {
public init() {
self.init(wrappedValue: nil)
}
public init<T>(
publisher: T
) where T: Publisher, T.Output == Value, T.Failure == Never {
self.init(publisher: publisher, defaultValue: nil)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment