Skip to content

Instantly share code, notes, and snippets.

@rustle
Created December 23, 2022 16:12
Show Gist options
  • Save rustle/b10c8526c968871f21df44128e09dabb to your computer and use it in GitHub Desktop.
Save rustle/b10c8526c968871f21df44128e09dabb to your computer and use it in GitHub Desktop.
@available(iOS 16.0, macOS 13.0, watchOS 9.0, *)
@propertyWrapper
public struct AsyncPublished<Value> {
@available(*, unavailable, message: "@AsyncPublished is only available on properties of classes")
public var wrappedValue: Value {
get { fatalError() }
set { fatalError() } // swiftlint:disable:this unused_setter_value
}
public let projectedValue: AsyncStream<Value>
public init(initialValue: Value) {
self.init(wrappedValue: initialValue)
}
public init(wrappedValue: Value) {
storage = wrappedValue
var con: AsyncStream<Value>.Continuation!
let str = AsyncStream<Value> {
con = $0
}
self.projectedValue = str
self.continuation = con
}
public static subscript<EnclosingSelf: AnyObject>(
_enclosingInstance object: EnclosingSelf,
wrapped wrappedKeyPath: ReferenceWritableKeyPath<EnclosingSelf, Value>,
storage storageKeyPath: ReferenceWritableKeyPath<EnclosingSelf, AsyncPublished<Value>>
) -> Value {
get {
return object[keyPath: storageKeyPath].storage
}
set {
object[keyPath: storageKeyPath].storage = newValue
object[keyPath: storageKeyPath].continuation.yield(newValue)
}
}
private let continuation: AsyncStream<Value>.Continuation
private var storage: Value
}
actor Thingy {
@AsyncPublished var value: String = ""
func update(_ value: String) {
self.value = value
}
}
let thingy = Thingy()
Task {
for await value in await thingy.$value {
print(value)
}
}
Task {
await thingy.update("1")
await thingy.update("2")
await thingy.update("3")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment